build: ensure sys/select.h is included
[coreutils.git] / src / wc.c
blob179abbe2c3919e4bc17ffc292ac302cf5dc47a70
1 /* wc - print the number of lines, words, and bytes in files
2 Copyright (C) 1985-2019 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Paul Rubin, phr@ocf.berkeley.edu
18 and David MacKenzie, djm@gnu.ai.mit.edu. */
20 #include <config.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include <getopt.h>
25 #include <sys/types.h>
26 #include <wchar.h>
27 #include <wctype.h>
29 #include "system.h"
30 #include "argv-iter.h"
31 #include "die.h"
32 #include "error.h"
33 #include "fadvise.h"
34 #include "mbchar.h"
35 #include "physmem.h"
36 #include "readtokens0.h"
37 #include "safe-read.h"
38 #include "stat-size.h"
39 #include "xbinary-io.h"
41 #if !defined iswspace && !HAVE_ISWSPACE
42 # define iswspace(wc) \
43 ((wc) == to_uchar (wc) && isspace (to_uchar (wc)))
44 #endif
46 /* The official name of this program (e.g., no 'g' prefix). */
47 #define PROGRAM_NAME "wc"
49 #define AUTHORS \
50 proper_name ("Paul Rubin"), \
51 proper_name ("David MacKenzie")
53 /* Size of atomic reads. */
54 #define BUFFER_SIZE (16 * 1024)
56 /* Cumulative number of lines, words, chars and bytes in all files so far.
57 max_line_length is the maximum over all files processed so far. */
58 static uintmax_t total_lines;
59 static uintmax_t total_words;
60 static uintmax_t total_chars;
61 static uintmax_t total_bytes;
62 static uintmax_t max_line_length;
64 /* Which counts to print. */
65 static bool print_lines, print_words, print_chars, print_bytes;
66 static bool print_linelength;
68 /* The print width of each count. */
69 static int number_width;
71 /* True if we have ever read the standard input. */
72 static bool have_read_stdin;
74 /* Used to determine if file size can be determined without reading. */
75 static size_t page_size;
77 /* The result of calling fstat or stat on a file descriptor or file. */
78 struct fstatus
80 /* If positive, fstat or stat has not been called yet. Otherwise,
81 this is the value returned from fstat or stat. */
82 int failed;
84 /* If FAILED is zero, this is the file's status. */
85 struct stat st;
88 /* For long options that have no equivalent short option, use a
89 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
90 enum
92 FILES0_FROM_OPTION = CHAR_MAX + 1
95 static struct option const longopts[] =
97 {"bytes", no_argument, NULL, 'c'},
98 {"chars", no_argument, NULL, 'm'},
99 {"lines", no_argument, NULL, 'l'},
100 {"words", no_argument, NULL, 'w'},
101 {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
102 {"max-line-length", no_argument, NULL, 'L'},
103 {GETOPT_HELP_OPTION_DECL},
104 {GETOPT_VERSION_OPTION_DECL},
105 {NULL, 0, NULL, 0}
108 void
109 usage (int status)
111 if (status != EXIT_SUCCESS)
112 emit_try_help ();
113 else
115 printf (_("\
116 Usage: %s [OPTION]... [FILE]...\n\
117 or: %s [OPTION]... --files0-from=F\n\
119 program_name, program_name);
120 fputs (_("\
121 Print newline, word, and byte counts for each FILE, and a total line if\n\
122 more than one FILE is specified. A word is a non-zero-length sequence of\n\
123 characters delimited by white space.\n\
124 "), stdout);
126 emit_stdin_note ();
128 fputs (_("\
130 The options below may be used to select which counts are printed, always in\n\
131 the following order: newline, word, character, byte, maximum line length.\n\
132 -c, --bytes print the byte counts\n\
133 -m, --chars print the character counts\n\
134 -l, --lines print the newline counts\n\
135 "), stdout);
136 fputs (_("\
137 --files0-from=F read input from the files specified by\n\
138 NUL-terminated names in file F;\n\
139 If F is - then read names from standard input\n\
140 -L, --max-line-length print the maximum display width\n\
141 -w, --words print the word counts\n\
142 "), stdout);
143 fputs (HELP_OPTION_DESCRIPTION, stdout);
144 fputs (VERSION_OPTION_DESCRIPTION, stdout);
145 emit_ancillary_info (PROGRAM_NAME);
147 exit (status);
150 /* FILE is the name of the file (or NULL for standard input)
151 associated with the specified counters. */
152 static void
153 write_counts (uintmax_t lines,
154 uintmax_t words,
155 uintmax_t chars,
156 uintmax_t bytes,
157 uintmax_t linelength,
158 const char *file)
160 static char const format_sp_int[] = " %*s";
161 char const *format_int = format_sp_int + 1;
162 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
164 if (print_lines)
166 printf (format_int, number_width, umaxtostr (lines, buf));
167 format_int = format_sp_int;
169 if (print_words)
171 printf (format_int, number_width, umaxtostr (words, buf));
172 format_int = format_sp_int;
174 if (print_chars)
176 printf (format_int, number_width, umaxtostr (chars, buf));
177 format_int = format_sp_int;
179 if (print_bytes)
181 printf (format_int, number_width, umaxtostr (bytes, buf));
182 format_int = format_sp_int;
184 if (print_linelength)
186 printf (format_int, number_width, umaxtostr (linelength, buf));
188 if (file)
189 printf (" %s", strchr (file, '\n') ? quotef (file) : file);
190 putchar ('\n');
193 /* Count words. FILE_X is the name of the file (or NULL for standard
194 input) that is open on descriptor FD. *FSTATUS is its status.
195 CURRENT_POS is the current file offset if known, negative if unknown.
196 Return true if successful. */
197 static bool
198 wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos)
200 bool ok = true;
201 char buf[BUFFER_SIZE + 1];
202 size_t bytes_read;
203 uintmax_t lines, words, chars, bytes, linelength;
204 bool count_bytes, count_chars, count_complicated;
205 char const *file = file_x ? file_x : _("standard input");
207 lines = words = chars = bytes = linelength = 0;
209 /* If in the current locale, chars are equivalent to bytes, we prefer
210 counting bytes, because that's easier. */
211 #if MB_LEN_MAX > 1
212 if (MB_CUR_MAX > 1)
214 count_bytes = print_bytes;
215 count_chars = print_chars;
217 else
218 #endif
220 count_bytes = print_bytes || print_chars;
221 count_chars = false;
223 count_complicated = print_words || print_linelength;
225 /* Advise the kernel of our access pattern only if we will read(). */
226 if (!count_bytes || count_chars || print_lines || count_complicated)
227 fdadvise (fd, 0, 0, FADVISE_SEQUENTIAL);
229 /* When counting only bytes, save some line- and word-counting
230 overhead. If FD is a 'regular' Unix file, using lseek is enough
231 to get its 'size' in bytes. Otherwise, read blocks of BUFFER_SIZE
232 bytes at a time until EOF. Note that the 'size' (number of bytes)
233 that wc reports is smaller than stats.st_size when the file is not
234 positioned at its beginning. That's why the lseek calls below are
235 necessary. For example the command
236 '(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
237 should make wc report '0' bytes. */
239 if (count_bytes && !count_chars && !print_lines && !count_complicated)
241 bool skip_read = false;
243 if (0 < fstatus->failed)
244 fstatus->failed = fstat (fd, &fstatus->st);
246 /* For sized files, seek to one st_blksize before EOF rather than to EOF.
247 This works better for files in proc-like file systems where
248 the size is only approximate. */
249 if (! fstatus->failed && usable_st_size (&fstatus->st)
250 && 0 <= fstatus->st.st_size)
252 size_t end_pos = fstatus->st.st_size;
253 if (current_pos < 0)
254 current_pos = lseek (fd, 0, SEEK_CUR);
256 if (end_pos % page_size)
258 /* We only need special handling of /proc and /sys files etc.
259 when they're a multiple of PAGE_SIZE. In the common case
260 for files with st_size not a multiple of PAGE_SIZE,
261 it's more efficient and accurate to use st_size.
263 Be careful here. The current position may actually be
264 beyond the end of the file. As in the example above. */
266 bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
267 skip_read = true;
269 else
271 off_t hi_pos = end_pos - end_pos % (ST_BLKSIZE (fstatus->st) + 1);
272 if (0 <= current_pos && current_pos < hi_pos
273 && 0 <= lseek (fd, hi_pos, SEEK_CUR))
274 bytes = hi_pos - current_pos;
278 if (! skip_read)
280 fdadvise (fd, 0, 0, FADVISE_SEQUENTIAL);
281 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
283 if (bytes_read == SAFE_READ_ERROR)
285 error (0, errno, "%s", quotef (file));
286 ok = false;
287 break;
289 bytes += bytes_read;
293 else if (!count_chars && !count_complicated)
295 /* Use a separate loop when counting only lines or lines and bytes --
296 but not chars or words. */
297 bool long_lines = false;
298 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
300 if (bytes_read == SAFE_READ_ERROR)
302 error (0, errno, "%s", quotef (file));
303 ok = false;
304 break;
307 bytes += bytes_read;
309 char *p = buf;
310 char *end = p + bytes_read;
311 uintmax_t plines = lines;
313 if (! long_lines)
315 /* Avoid function call overhead for shorter lines. */
316 while (p != end)
317 lines += *p++ == '\n';
319 else
321 /* memchr is more efficient with longer lines. */
322 while ((p = memchr (p, '\n', end - p)))
324 ++p;
325 ++lines;
329 /* If the average line length in the block is >= 15, then use
330 memchr for the next block, where system specific optimizations
331 may outweigh function call overhead.
332 FIXME: This line length was determined in 2015, on both
333 x86_64 and ppc64, but it's worth re-evaluating in future with
334 newer compilers, CPUs, or memchr() implementations etc. */
335 if (lines - plines <= bytes_read / 15)
336 long_lines = true;
337 else
338 long_lines = false;
341 #if MB_LEN_MAX > 1
342 # define SUPPORT_OLD_MBRTOWC 1
343 else if (MB_CUR_MAX > 1)
345 bool in_word = false;
346 uintmax_t linepos = 0;
347 mbstate_t state = { 0, };
348 bool in_shift = false;
349 # if SUPPORT_OLD_MBRTOWC
350 /* Back-up the state before each multibyte character conversion and
351 move the last incomplete character of the buffer to the front
352 of the buffer. This is needed because we don't know whether
353 the 'mbrtowc' function updates the state when it returns -2, --
354 this is the ISO C 99 and glibc-2.2 behaviour - or not - amended
355 ANSI C, glibc-2.1 and Solaris 5.7 behaviour. We don't have an
356 autoconf test for this, yet. */
357 size_t prev = 0; /* number of bytes carried over from previous round */
358 # else
359 const size_t prev = 0;
360 # endif
362 while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
364 const char *p;
365 # if SUPPORT_OLD_MBRTOWC
366 mbstate_t backup_state;
367 # endif
368 if (bytes_read == SAFE_READ_ERROR)
370 error (0, errno, "%s", quotef (file));
371 ok = false;
372 break;
375 bytes += bytes_read;
376 p = buf;
377 bytes_read += prev;
380 wchar_t wide_char;
381 size_t n;
382 bool wide = true;
384 if (!in_shift && is_basic (*p))
386 /* Handle most ASCII characters quickly, without calling
387 mbrtowc(). */
388 n = 1;
389 wide_char = *p;
390 wide = false;
392 else
394 in_shift = true;
395 # if SUPPORT_OLD_MBRTOWC
396 backup_state = state;
397 # endif
398 n = mbrtowc (&wide_char, p, bytes_read, &state);
399 if (n == (size_t) -2)
401 # if SUPPORT_OLD_MBRTOWC
402 state = backup_state;
403 # endif
404 break;
406 if (n == (size_t) -1)
408 /* Remember that we read a byte, but don't complain
409 about the error. Because of the decoding error,
410 this is a considered to be byte but not a
411 character (that is, chars is not incremented). */
412 p++;
413 bytes_read--;
414 continue;
416 if (mbsinit (&state))
417 in_shift = false;
418 if (n == 0)
420 wide_char = 0;
421 n = 1;
425 switch (wide_char)
427 case '\n':
428 lines++;
429 FALLTHROUGH;
430 case '\r':
431 case '\f':
432 if (linepos > linelength)
433 linelength = linepos;
434 linepos = 0;
435 goto mb_word_separator;
436 case '\t':
437 linepos += 8 - (linepos % 8);
438 goto mb_word_separator;
439 case ' ':
440 linepos++;
441 FALLTHROUGH;
442 case '\v':
443 mb_word_separator:
444 words += in_word;
445 in_word = false;
446 break;
447 default:
448 if (wide && iswprint (wide_char))
450 /* wcwidth can be expensive on OSX for example,
451 so avoid if uneeded. */
452 if (print_linelength)
454 int width = wcwidth (wide_char);
455 if (width > 0)
456 linepos += width;
458 if (iswspace (wide_char))
459 goto mb_word_separator;
460 in_word = true;
462 else if (!wide && isprint (to_uchar (*p)))
464 linepos++;
465 if (isspace (to_uchar (*p)))
466 goto mb_word_separator;
467 in_word = true;
469 break;
472 p += n;
473 bytes_read -= n;
474 chars++;
476 while (bytes_read > 0);
478 # if SUPPORT_OLD_MBRTOWC
479 if (bytes_read > 0)
481 if (bytes_read == BUFFER_SIZE)
483 /* Encountered a very long redundant shift sequence. */
484 p++;
485 bytes_read--;
487 memmove (buf, p, bytes_read);
489 prev = bytes_read;
490 # endif
492 if (linepos > linelength)
493 linelength = linepos;
494 words += in_word;
496 #endif
497 else
499 bool in_word = false;
500 uintmax_t linepos = 0;
502 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
504 const char *p = buf;
505 if (bytes_read == SAFE_READ_ERROR)
507 error (0, errno, "%s", quotef (file));
508 ok = false;
509 break;
512 bytes += bytes_read;
515 switch (*p++)
517 case '\n':
518 lines++;
519 FALLTHROUGH;
520 case '\r':
521 case '\f':
522 if (linepos > linelength)
523 linelength = linepos;
524 linepos = 0;
525 goto word_separator;
526 case '\t':
527 linepos += 8 - (linepos % 8);
528 goto word_separator;
529 case ' ':
530 linepos++;
531 FALLTHROUGH;
532 case '\v':
533 word_separator:
534 words += in_word;
535 in_word = false;
536 break;
537 default:
538 if (isprint (to_uchar (p[-1])))
540 linepos++;
541 if (isspace (to_uchar (p[-1])))
542 goto word_separator;
543 in_word = true;
545 break;
548 while (--bytes_read);
550 if (linepos > linelength)
551 linelength = linepos;
552 words += in_word;
555 if (count_chars < print_chars)
556 chars = bytes;
558 write_counts (lines, words, chars, bytes, linelength, file_x);
559 total_lines += lines;
560 total_words += words;
561 total_chars += chars;
562 total_bytes += bytes;
563 if (linelength > max_line_length)
564 max_line_length = linelength;
566 return ok;
569 static bool
570 wc_file (char const *file, struct fstatus *fstatus)
572 if (! file || STREQ (file, "-"))
574 have_read_stdin = true;
575 xset_binary_mode (STDIN_FILENO, O_BINARY);
576 return wc (STDIN_FILENO, file, fstatus, -1);
578 else
580 int fd = open (file, O_RDONLY | O_BINARY);
581 if (fd == -1)
583 error (0, errno, "%s", quotef (file));
584 return false;
586 else
588 bool ok = wc (fd, file, fstatus, 0);
589 if (close (fd) != 0)
591 error (0, errno, "%s", quotef (file));
592 return false;
594 return ok;
599 /* Return the file status for the NFILES files addressed by FILE.
600 Optimize the case where only one number is printed, for just one
601 file; in that case we can use a print width of 1, so we don't need
602 to stat the file. Handle the case of (nfiles == 0) in the same way;
603 that happens when we don't know how long the list of file names will be. */
605 static struct fstatus *
606 get_input_fstatus (size_t nfiles, char *const *file)
608 struct fstatus *fstatus = xnmalloc (nfiles ? nfiles : 1, sizeof *fstatus);
610 if (nfiles == 0
611 || (nfiles == 1
612 && ((print_lines + print_words + print_chars
613 + print_bytes + print_linelength)
614 == 1)))
615 fstatus[0].failed = 1;
616 else
618 for (size_t i = 0; i < nfiles; i++)
619 fstatus[i].failed = (! file[i] || STREQ (file[i], "-")
620 ? fstat (STDIN_FILENO, &fstatus[i].st)
621 : stat (file[i], &fstatus[i].st));
624 return fstatus;
627 /* Return a print width suitable for the NFILES files whose status is
628 recorded in FSTATUS. Optimize the same special case that
629 get_input_fstatus optimizes. */
631 static int _GL_ATTRIBUTE_PURE
632 compute_number_width (size_t nfiles, struct fstatus const *fstatus)
634 int width = 1;
636 if (0 < nfiles && fstatus[0].failed <= 0)
638 int minimum_width = 1;
639 uintmax_t regular_total = 0;
641 for (size_t i = 0; i < nfiles; i++)
642 if (! fstatus[i].failed)
644 if (S_ISREG (fstatus[i].st.st_mode))
645 regular_total += fstatus[i].st.st_size;
646 else
647 minimum_width = 7;
650 for (; 10 <= regular_total; regular_total /= 10)
651 width++;
652 if (width < minimum_width)
653 width = minimum_width;
656 return width;
661 main (int argc, char **argv)
663 bool ok;
664 int optc;
665 size_t nfiles;
666 char **files;
667 char *files_from = NULL;
668 struct fstatus *fstatus;
669 struct Tokens tok;
671 initialize_main (&argc, &argv);
672 set_program_name (argv[0]);
673 setlocale (LC_ALL, "");
674 bindtextdomain (PACKAGE, LOCALEDIR);
675 textdomain (PACKAGE);
677 atexit (close_stdout);
679 page_size = getpagesize ();
680 /* Line buffer stdout to ensure lines are written atomically and immediately
681 so that processes running in parallel do not intersperse their output. */
682 setvbuf (stdout, NULL, _IOLBF, 0);
684 print_lines = print_words = print_chars = print_bytes = false;
685 print_linelength = false;
686 total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
688 while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
689 switch (optc)
691 case 'c':
692 print_bytes = true;
693 break;
695 case 'm':
696 print_chars = true;
697 break;
699 case 'l':
700 print_lines = true;
701 break;
703 case 'w':
704 print_words = true;
705 break;
707 case 'L':
708 print_linelength = true;
709 break;
711 case FILES0_FROM_OPTION:
712 files_from = optarg;
713 break;
715 case_GETOPT_HELP_CHAR;
717 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
719 default:
720 usage (EXIT_FAILURE);
723 if (! (print_lines || print_words || print_chars || print_bytes
724 || print_linelength))
725 print_lines = print_words = print_bytes = true;
727 bool read_tokens = false;
728 struct argv_iterator *ai;
729 if (files_from)
731 FILE *stream;
733 /* When using --files0-from=F, you may not specify any files
734 on the command-line. */
735 if (optind < argc)
737 error (0, 0, _("extra operand %s"), quoteaf (argv[optind]));
738 fprintf (stderr, "%s\n",
739 _("file operands cannot be combined with --files0-from"));
740 usage (EXIT_FAILURE);
743 if (STREQ (files_from, "-"))
744 stream = stdin;
745 else
747 stream = fopen (files_from, "r");
748 if (stream == NULL)
749 die (EXIT_FAILURE, errno, _("cannot open %s for reading"),
750 quoteaf (files_from));
753 /* Read the file list into RAM if we can detect its size and that
754 size is reasonable. Otherwise, we'll read a name at a time. */
755 struct stat st;
756 if (fstat (fileno (stream), &st) == 0
757 && S_ISREG (st.st_mode)
758 && st.st_size <= MIN (10 * 1024 * 1024, physmem_available () / 2))
760 read_tokens = true;
761 readtokens0_init (&tok);
762 if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
763 die (EXIT_FAILURE, 0, _("cannot read file names from %s"),
764 quoteaf (files_from));
765 files = tok.tok;
766 nfiles = tok.n_tok;
767 ai = argv_iter_init_argv (files);
769 else
771 files = NULL;
772 nfiles = 0;
773 ai = argv_iter_init_stream (stream);
776 else
778 static char *stdin_only[] = { NULL };
779 files = (optind < argc ? argv + optind : stdin_only);
780 nfiles = (optind < argc ? argc - optind : 1);
781 ai = argv_iter_init_argv (files);
784 if (!ai)
785 xalloc_die ();
787 fstatus = get_input_fstatus (nfiles, files);
788 number_width = compute_number_width (nfiles, fstatus);
790 ok = true;
791 for (int i = 0; /* */; i++)
793 bool skip_file = false;
794 enum argv_iter_err ai_err;
795 char *file_name = argv_iter (ai, &ai_err);
796 if (!file_name)
798 switch (ai_err)
800 case AI_ERR_EOF:
801 goto argv_iter_done;
802 case AI_ERR_READ:
803 error (0, errno, _("%s: read error"),
804 quotef (files_from));
805 ok = false;
806 goto argv_iter_done;
807 case AI_ERR_MEM:
808 xalloc_die ();
809 default:
810 assert (!"unexpected error code from argv_iter");
813 if (files_from && STREQ (files_from, "-") && STREQ (file_name, "-"))
815 /* Give a better diagnostic in an unusual case:
816 printf - | wc --files0-from=- */
817 error (0, 0, _("when reading file names from stdin, "
818 "no file name of %s allowed"),
819 quoteaf (file_name));
820 skip_file = true;
823 if (!file_name[0])
825 /* Diagnose a zero-length file name. When it's one
826 among many, knowing the record number may help.
827 FIXME: currently print the record number only with
828 --files0-from=FILE. Maybe do it for argv, too? */
829 if (files_from == NULL)
830 error (0, 0, "%s", _("invalid zero-length file name"));
831 else
833 /* Using the standard 'filename:line-number:' prefix here is
834 not totally appropriate, since NUL is the separator, not NL,
835 but it might be better than nothing. */
836 unsigned long int file_number = argv_iter_n_args (ai);
837 error (0, 0, "%s:%lu: %s", quotef (files_from),
838 file_number, _("invalid zero-length file name"));
840 skip_file = true;
843 if (skip_file)
844 ok = false;
845 else
846 ok &= wc_file (file_name, &fstatus[nfiles ? i : 0]);
848 if (! nfiles)
849 fstatus[0].failed = 1;
851 argv_iter_done:
853 /* No arguments on the command line is fine. That means read from stdin.
854 However, no arguments on the --files0-from input stream is an error
855 means don't read anything. */
856 if (ok && !files_from && argv_iter_n_args (ai) == 0)
857 ok &= wc_file (NULL, &fstatus[0]);
859 if (read_tokens)
860 readtokens0_free (&tok);
862 if (1 < argv_iter_n_args (ai))
863 write_counts (total_lines, total_words, total_chars, total_bytes,
864 max_line_length, _("total"));
866 argv_iter_free (ai);
868 free (fstatus);
870 if (have_read_stdin && close (STDIN_FILENO) != 0)
871 die (EXIT_FAILURE, errno, "-");
873 return ok ? EXIT_SUCCESS : EXIT_FAILURE;