121588Sdist /* 233163Sbostic * Copyright (c) 1980, 1987 Regents of the University of California. 333163Sbostic * All rights reserved. 433163Sbostic * 542785Sbostic * %sccs.include.redist.c% 621588Sdist */ 721588Sdist 821588Sdist #ifndef lint 921588Sdist char copyright[] = 10*51587Sbostic "@(#) Copyright (c) 1987, 1991 Regents of the University of California.\n\ 1121588Sdist All rights reserved.\n"; 1233163Sbostic #endif /* not lint */ 1321588Sdist 1421588Sdist #ifndef lint 15*51587Sbostic static char sccsid[] = "@(#)wc.c 5.8 (Berkeley) 11/06/91"; 1633163Sbostic #endif /* not lint */ 1721588Sdist 1830103Sbostic #include <sys/param.h> 1930103Sbostic #include <sys/stat.h> 20*51587Sbostic #include <fcntl.h> 21*51587Sbostic #include <unistd.h> 22*51587Sbostic #include <errno.h> 231161Sbill #include <stdio.h> 24*51587Sbostic #include <stdlib.h> 25*51587Sbostic #include <string.h> 26*51587Sbostic #include <ctype.h> 271161Sbill 28*51587Sbostic u_long tlinect, twordct, tcharct; 29*51587Sbostic int doline, doword, dochar; 3030103Sbostic 31*51587Sbostic void cnt __P((char *)); 32*51587Sbostic void err __P((const char *, ...)); 33*51587Sbostic void usage __P((void)); 3430103Sbostic 35*51587Sbostic int 3635284Sbostic main(argc, argv) 3733163Sbostic int argc; 38*51587Sbostic char *argv[]; 391161Sbill { 4033163Sbostic register int ch; 4135284Sbostic int total; 421161Sbill 43*51587Sbostic while ((ch = getopt(argc, argv, "lwc")) != EOF) 44*51587Sbostic switch((char)ch) { 45*51587Sbostic case 'l': 46*51587Sbostic doline = 1; 47*51587Sbostic break; 48*51587Sbostic case 'w': 49*51587Sbostic doword = 1; 50*51587Sbostic break; 51*51587Sbostic case 'c': 52*51587Sbostic dochar = 1; 53*51587Sbostic break; 54*51587Sbostic case '?': 55*51587Sbostic default: 56*51587Sbostic usage(); 57*51587Sbostic } 58*51587Sbostic argv += optind; 59*51587Sbostic argc -= optind; 60*51587Sbostic 61*51587Sbostic /* Wc's flags are on by default. */ 62*51587Sbostic if (doline + doword + dochar == 0) 6333163Sbostic doline = doword = dochar = 1; 6430103Sbostic 6535284Sbostic total = 0; 6635284Sbostic if (!*argv) { 67*51587Sbostic cnt(NULL); 68*51587Sbostic (void)printf("\n"); 691161Sbill } 7035284Sbostic else do { 7135284Sbostic cnt(*argv); 72*51587Sbostic (void)printf(" %s\n", *argv); 7335284Sbostic ++total; 7430103Sbostic } while(*++argv); 7530103Sbostic 7635284Sbostic if (total > 1) { 7735284Sbostic if (doline) 78*51587Sbostic (void)printf(" %7ld", tlinect); 7935284Sbostic if (doword) 80*51587Sbostic (void)printf(" %7ld", twordct); 8135284Sbostic if (dochar) 82*51587Sbostic (void)printf(" %7ld", tcharct); 83*51587Sbostic (void)printf(" total\n"); 8435284Sbostic } 8533163Sbostic exit(0); 8630103Sbostic } 8730103Sbostic 88*51587Sbostic void 8930103Sbostic cnt(file) 9033163Sbostic char *file; 9130103Sbostic { 92*51587Sbostic register u_char *p; 9333163Sbostic register short gotsp; 94*51587Sbostic register int ch, len; 95*51587Sbostic register u_long linect, wordct, charct; 96*51587Sbostic struct stat sb; 9733163Sbostic int fd; 9833163Sbostic u_char buf[MAXBSIZE]; 9930103Sbostic 100*51587Sbostic fd = STDIN_FILENO; 10130103Sbostic linect = wordct = charct = 0; 10230103Sbostic if (file) { 103*51587Sbostic if ((fd = open(file, O_RDONLY, 0)) < 0) 104*51587Sbostic err("%s: %s", file, strerror(errno)); 105*51587Sbostic if (doword) 106*51587Sbostic goto word; 107*51587Sbostic /* 108*51587Sbostic * Line counting is split out because it's a lot faster to get 109*51587Sbostic * lines than to get words, since the word count requires some 110*51587Sbostic * logic. 111*51587Sbostic */ 112*51587Sbostic if (doline) { 113*51587Sbostic while (len = read(fd, buf, MAXBSIZE)) { 114*51587Sbostic if (len == -1) 115*51587Sbostic err("%s: %s", file, strerror(errno)); 116*51587Sbostic charct += len; 117*51587Sbostic for (p = buf; len--; ++p) 118*51587Sbostic if (*p == '\n') 119*51587Sbostic ++linect; 1201161Sbill } 121*51587Sbostic tlinect += linect; 122*51587Sbostic (void)printf(" %7lu", linect); 12330103Sbostic if (dochar) { 124*51587Sbostic tcharct += charct; 125*51587Sbostic (void)printf(" %7lu", charct); 1261161Sbill } 127*51587Sbostic (void)close(fd); 128*51587Sbostic return; 1291161Sbill } 130*51587Sbostic /* 131*51587Sbostic * If all we need is the number of characters and it's a 132*51587Sbostic * regular or linked file, just stat the puppy. 133*51587Sbostic */ 134*51587Sbostic if (dochar) { 135*51587Sbostic if (fstat(fd, &sb)) 136*51587Sbostic err("%s: %s", file, strerror(errno)); 137*51587Sbostic if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) { 138*51587Sbostic (void)printf(" %7lu", sb.st_size); 139*51587Sbostic tcharct += sb.st_size; 140*51587Sbostic (void)close(fd); 141*51587Sbostic return; 142*51587Sbostic } 143*51587Sbostic } 14430103Sbostic } 145*51587Sbostic 146*51587Sbostic /* Do it the hard way... */ 147*51587Sbostic word: for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) { 148*51587Sbostic if (len == -1) 149*51587Sbostic err("%s: %s", file, strerror(errno)); 150*51587Sbostic /* 151*51587Sbostic * This loses in the presence of multi-byte characters. 152*51587Sbostic * To do it right would require a function to return a 153*51587Sbostic * character while knowing how many bytes it consumed. 154*51587Sbostic */ 15530103Sbostic charct += len; 156*51587Sbostic for (p = buf; len--;) { 157*51587Sbostic ch = *p++; 158*51587Sbostic if (ch == '\n') 159*51587Sbostic ++linect; 160*51587Sbostic if (isspace(ch)) 161*51587Sbostic gotsp = 1; 162*51587Sbostic else if (gotsp) { 163*51587Sbostic gotsp = 0; 164*51587Sbostic ++wordct; 16530103Sbostic } 166*51587Sbostic } 16730103Sbostic } 16830103Sbostic if (doline) { 1691161Sbill tlinect += linect; 170*51587Sbostic (void)printf(" %7lu", linect); 17130103Sbostic } 17230103Sbostic if (doword) { 1731161Sbill twordct += wordct; 174*51587Sbostic (void)printf(" %7lu", wordct); 17530103Sbostic } 17630103Sbostic if (dochar) { 1771161Sbill tcharct += charct; 178*51587Sbostic (void)printf(" %7lu", charct); 1791161Sbill } 180*51587Sbostic (void)close(fd); 1811161Sbill } 182*51587Sbostic 183*51587Sbostic void 184*51587Sbostic usage() 185*51587Sbostic { 186*51587Sbostic (void)fprintf(stderr, "usage: wc [-clw] [files]\n"); 187*51587Sbostic exit(1); 188*51587Sbostic } 189*51587Sbostic 190*51587Sbostic #if __STDC__ 191*51587Sbostic #include <stdarg.h> 192*51587Sbostic #else 193*51587Sbostic #include <varargs.h> 194*51587Sbostic #endif 195*51587Sbostic 196*51587Sbostic void 197*51587Sbostic #if __STDC__ 198*51587Sbostic err(const char *fmt, ...) 199*51587Sbostic #else 200*51587Sbostic err(fmt, va_alist) 201*51587Sbostic char *fmt; 202*51587Sbostic va_dcl 203*51587Sbostic #endif 204*51587Sbostic { 205*51587Sbostic va_list ap; 206*51587Sbostic #if __STDC__ 207*51587Sbostic va_start(ap, fmt); 208*51587Sbostic #else 209*51587Sbostic va_start(ap); 210*51587Sbostic #endif 211*51587Sbostic (void)fprintf(stderr, "wc: "); 212*51587Sbostic (void)vfprintf(stderr, fmt, ap); 213*51587Sbostic va_end(ap); 214*51587Sbostic (void)fprintf(stderr, "\n"); 215*51587Sbostic exit(1); 216*51587Sbostic /* NOTREACHED */ 217*51587Sbostic } 218