1 /* wc - print the number of bytes, words, and lines in files
2 Copyright (C) 1985, 1991, 1995 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 2, or (at your option)
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, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Paul Rubin, phr@ocf.berkeley.edu
19 and David MacKenzie, djm@gnu.ai.mit.edu. */
25 #include <sys/types.h>
30 /* Size of atomic reads. */
31 #define BUFFER_SIZE (16 * 1024)
36 static void wc_file ();
37 static void write_counts ();
39 /* The name this program was run with. */
42 /* Cumulative number of lines, words, and chars in all files so far. */
43 static unsigned long total_lines
, total_words
, total_chars
;
45 /* Which counts to print. */
46 static int print_lines
, print_words
, print_chars
;
48 /* Nonzero if we have ever read the standard input. */
49 static int have_read_stdin
;
51 /* The error code to return to the system. */
52 static int exit_status
;
54 /* If non-zero, display usage information and exit. */
57 /* If non-zero, print the version on standard output then exits. */
58 static int show_version
;
60 static struct option
const longopts
[] =
62 {"bytes", no_argument
, NULL
, 'c'},
63 {"chars", no_argument
, NULL
, 'c'},
64 {"lines", no_argument
, NULL
, 'l'},
65 {"words", no_argument
, NULL
, 'w'},
66 {"help", no_argument
, &show_help
, 1},
67 {"version", no_argument
, &show_version
, 1},
76 fprintf (stderr
, "Try `%s --help' for more information.\n",
81 Usage: %s [OPTION]... [FILE]...\n\
85 Print line, word, and byte counts for each FILE, and a total line if\n\
86 more than one FILE is specified. With no FILE, or when FILE is -,\n\
87 read standard input.\n\
88 -l, --lines print the newline counts\n\
89 -w, --words print the word counts\n\
90 -c, --bytes, --chars print the byte counts\n\
91 --help display this help and exit\n\
92 --version output version information and exit\n\
106 program_name
= argv
[0];
108 print_lines
= print_words
= print_chars
= 0;
109 total_lines
= total_words
= total_chars
= 0;
111 while ((optc
= getopt_long (argc
, argv
, "clw", longopts
, (int *) 0)) != EOF
)
135 printf ("wc - %s\n", version_string
);
142 if (print_lines
+ print_words
+ print_chars
== 0)
143 print_lines
= print_words
= print_chars
= 1;
145 nfiles
= argc
- optind
;
154 for (; optind
< argc
; ++optind
)
155 wc_file (argv
[optind
]);
158 write_counts (total_lines
, total_words
, total_chars
, "total");
161 if (have_read_stdin
&& close (0))
162 error (1, errno
, "-");
171 if (!strcmp (file
, "-"))
178 int fd
= open (file
, O_RDONLY
);
181 error (0, errno
, "%s", file
);
188 error (0, errno
, "%s", file
);
199 char buf
[BUFFER_SIZE
+ 1];
200 register int bytes_read
;
201 register int in_word
= 0;
202 register unsigned long lines
, words
, chars
;
204 lines
= words
= chars
= 0;
206 /* When counting only bytes, save some line- and word-counting
207 overhead. If FD is a `regular' Unix file, using lseek is enough
208 to get its `size' in bytes. Otherwise, read blocks of BUFFER_SIZE
209 bytes at a time until EOF. Note that the `size' (number of bytes)
210 that wc reports is smaller than stats.st_size when the file is not
211 positioned at its beginning. That's why the lseek calls below are
212 necessary. For example the command
213 `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
214 should make wc report `0' bytes. */
216 if (print_chars
&& !print_words
&& !print_lines
)
218 off_t current_pos
, end_pos
;
221 if (fstat (fd
, &stats
) == 0 && S_ISREG (stats
.st_mode
)
222 && (current_pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
)) != -1
223 && (end_pos
= lseek (fd
, (off_t
) 0, SEEK_END
)) != -1)
226 /* Be careful here. The current position may actually be
227 beyond the end of the file. As in the example above. */
228 chars
= (diff
= end_pos
- current_pos
) < 0 ? 0 : diff
;
232 while ((bytes_read
= safe_read (fd
, buf
, BUFFER_SIZE
)) > 0)
238 error (0, errno
, "%s", file
);
243 else if (!print_words
)
245 /* Use a separate loop when counting only lines or lines and bytes --
247 while ((bytes_read
= safe_read (fd
, buf
, BUFFER_SIZE
)) > 0)
249 register char *p
= buf
;
251 while ((p
= memchr (p
, '\n', (buf
+ bytes_read
) - p
)))
260 error (0, errno
, "%s", file
);
266 while ((bytes_read
= safe_read (fd
, buf
, BUFFER_SIZE
)) > 0)
268 register char *p
= buf
;
294 while (--bytes_read
);
298 error (0, errno
, "%s", file
);
305 write_counts (lines
, words
, chars
, file
);
306 total_lines
+= lines
;
307 total_words
+= words
;
308 total_chars
+= chars
;
312 write_counts (lines
, words
, chars
, file
)
313 unsigned long lines
, words
, chars
;
317 printf ("%7lu", lines
);
322 printf ("%7lu", words
);
326 if (print_lines
|| print_words
)
328 printf ("%7lu", chars
);
331 printf (" %s", file
);