Annotation of src/usr.bin/wc/wc.c, Revision 1.1.1.1
1.1 deraadt 1: /*
2: * Copyright (c) 1980, 1987 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: */
33:
34: #ifndef lint
35: char copyright[] =
36: "@(#) Copyright (c) 1980, 1987 Regents of the University of California.\n\
37: All rights reserved.\n";
38: #endif /* not lint */
39:
40: #ifndef lint
41: /*static char sccsid[] = "from: @(#)wc.c 5.7 (Berkeley) 3/2/91";*/
42: static char rcsid[] = "$Id: wc.c,v 1.9 1994/01/03 03:11:06 andrew Exp $";
43: #endif /* not lint */
44:
45: /* wc line, word and char count */
46:
47: #include <stdio.h>
48: #include <stdlib.h>
49: #include <string.h>
50: #include <locale.h>
51: #include <ctype.h>
52: #include <errno.h>
53: #include <sys/param.h>
54: #include <sys/stat.h>
55: #include <sys/file.h>
56: #include <unistd.h>
57: #include <err.h>
58:
59: static void print_counts();
60: static void cnt();
61: static long tlinect, twordct, tcharct;
62: static int doline, doword, dochar;
63: static int rval = 0;
64:
65: int
66: main(argc, argv)
67: int argc;
68: char **argv;
69: {
70: extern int optind;
71: register int ch;
72:
73: setlocale(LC_ALL, "");
74:
75: while ((ch = getopt(argc, argv, "lwcm")) != -1)
76: switch((char)ch) {
77: case 'l':
78: doline = 1;
79: break;
80: case 'w':
81: doword = 1;
82: break;
83: case 'c':
84: case 'm':
85: dochar = 1;
86: break;
87: case '?':
88: default:
89: fprintf(stderr, "usage: wc [-c | -m] [-lw] [file ...]\n");
90: exit(1);
91: }
92: argv += optind;
93: argc -= optind;
94:
95: /*
96: * wc is unusual in that its flags are on by default, so,
97: * if you don't get any arguments, you have to turn them
98: * all on.
99: */
100: if (!doline && !doword && !dochar) {
101: doline = doword = dochar = 1;
102: }
103:
104: if (!*argv) {
105: cnt((char *)NULL);
106: } else {
107: int dototal = (argc > 1);
108:
109: do {
110: cnt(*argv);
111: } while(*++argv);
112:
113: if (dototal) {
114: print_counts (tlinect, twordct, tcharct, "total");
115: }
116: }
117:
118: exit(rval);
119: }
120:
121:
122: static void
123: cnt(file)
124: char *file;
125: {
126: register u_char *C;
127: register short gotsp;
128: register int len;
129: register long linect, wordct, charct;
130: struct stat sbuf;
131: int fd;
132: u_char buf[MAXBSIZE];
133:
134: linect = wordct = charct = 0;
135: if (file) {
136: if ((fd = open(file, O_RDONLY, 0)) < 0) {
137: warn ("%s", file);
138: rval = 1;
139: return;
140: }
141: } else {
142: fd = STDIN_FILENO;
143: }
144:
145: if (!doword) {
146: /*
147: * line counting is split out because it's a lot
148: * faster to get lines than to get words, since
149: * the word count requires some logic.
150: */
151: if (doline) {
152: while((len = read(fd, buf, MAXBSIZE)) > 0) {
153: charct += len;
154: for (C = buf; len--; ++C)
155: if (*C == '\n')
156: ++linect;
157: }
158: if (len == -1) {
159: warn ("%s", file);
160: rval = 1;
161: }
162: }
163:
164: /*
165: * if all we need is the number of characters and
166: * it's a directory or a regular or linked file, just
167: * stat the puppy. We avoid testing for it not being
168: * a special device in case someone adds a new type
169: * of inode.
170: */
171: else if (dochar) {
172: int ifmt;
173:
174: if (fstat(fd, &sbuf)) {
175: warn ("%s", file);
176: rval = 1;
177: } else {
178: ifmt = sbuf.st_mode & S_IFMT;
179: if (ifmt == S_IFREG || ifmt == S_IFLNK
180: || ifmt == S_IFDIR) {
181: charct = sbuf.st_size;
182: } else {
183: while((len = read(fd, buf, MAXBSIZE)) > 0)
184: charct += len;
185: if (len == -1) {
186: warn ("%s", file);
187: rval = 1;
188: }
189: }
190: }
191: }
192: }
193: else
194: {
195: /* do it the hard way... */
196: gotsp = 1;
197: while ((len = read(fd, buf, MAXBSIZE)) > 0) {
198: charct += len;
199: for (C = buf; len--; ++C) {
200: if (isspace (*C)) {
201: gotsp = 1;
202: if (*C == '\n') {
203: ++linect;
204: }
205: } else {
206: /*
207: * This line implements the POSIX
208: * spec, i.e. a word is a "maximal
209: * string of characters delimited by
210: * whitespace." Notice nothing was
211: * said about a character being
212: * printing or non-printing.
213: */
214: if (gotsp) {
215: gotsp = 0;
216: ++wordct;
217: }
218: }
219: }
220: }
221: if (len == -1) {
222: warn ("%s", file);
223: rval = 1;
224: }
225: }
226:
227: print_counts (linect, wordct, charct, file ? file : "");
228:
229: /* don't bother checkint doline, doword, or dochar --- speeds
230: up the common case */
231: tlinect += linect;
232: twordct += wordct;
233: tcharct += charct;
234:
235: if (close(fd)) {
236: warn ("%s", file);
237: rval = 1;
238: }
239: }
240:
241:
242: void
243: print_counts (lines, words, chars, name)
244: long lines;
245: long words;
246: long chars;
247: char *name;
248: {
249:
250: if (doline)
251: printf(" %7ld", lines);
252: if (doword)
253: printf(" %7ld", words);
254: if (dochar)
255: printf(" %7ld", chars);
256:
257: printf (" %s\n", name);
258: }