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[] = 1051587Sbostic "@(#) 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*59588Sbostic static char sccsid[] = "@(#)wc.c 5.9 (Berkeley) 04/30/93"; 1633163Sbostic #endif /* not lint */ 1721588Sdist 1830103Sbostic #include <sys/param.h> 1930103Sbostic #include <sys/stat.h> 2051587Sbostic #include <fcntl.h> 2151587Sbostic #include <unistd.h> 2251587Sbostic #include <errno.h> 231161Sbill #include <stdio.h> 2451587Sbostic #include <stdlib.h> 2551587Sbostic #include <string.h> 2651587Sbostic #include <ctype.h> 271161Sbill 2851587Sbostic u_long tlinect, twordct, tcharct; 2951587Sbostic int doline, doword, dochar; 3030103Sbostic 3151587Sbostic void cnt __P((char *)); 3251587Sbostic void err __P((const char *, ...)); 3351587Sbostic void usage __P((void)); 3430103Sbostic 3551587Sbostic int 3635284Sbostic main(argc, argv) 3733163Sbostic int argc; 3851587Sbostic char *argv[]; 391161Sbill { 4033163Sbostic register int ch; 4135284Sbostic int total; 421161Sbill 4351587Sbostic while ((ch = getopt(argc, argv, "lwc")) != EOF) 4451587Sbostic switch((char)ch) { 4551587Sbostic case 'l': 4651587Sbostic doline = 1; 4751587Sbostic break; 4851587Sbostic case 'w': 4951587Sbostic doword = 1; 5051587Sbostic break; 5151587Sbostic case 'c': 5251587Sbostic dochar = 1; 5351587Sbostic break; 5451587Sbostic case '?': 5551587Sbostic default: 5651587Sbostic usage(); 5751587Sbostic } 5851587Sbostic argv += optind; 5951587Sbostic argc -= optind; 6051587Sbostic 6151587Sbostic /* Wc's flags are on by default. */ 6251587Sbostic if (doline + doword + dochar == 0) 6333163Sbostic doline = doword = dochar = 1; 6430103Sbostic 6535284Sbostic total = 0; 6635284Sbostic if (!*argv) { 6751587Sbostic cnt(NULL); 6851587Sbostic (void)printf("\n"); 691161Sbill } 7035284Sbostic else do { 7135284Sbostic cnt(*argv); 7251587Sbostic (void)printf(" %s\n", *argv); 7335284Sbostic ++total; 7430103Sbostic } while(*++argv); 7530103Sbostic 7635284Sbostic if (total > 1) { 7735284Sbostic if (doline) 7851587Sbostic (void)printf(" %7ld", tlinect); 7935284Sbostic if (doword) 8051587Sbostic (void)printf(" %7ld", twordct); 8135284Sbostic if (dochar) 8251587Sbostic (void)printf(" %7ld", tcharct); 8351587Sbostic (void)printf(" total\n"); 8435284Sbostic } 8533163Sbostic exit(0); 8630103Sbostic } 8730103Sbostic 8851587Sbostic void 8930103Sbostic cnt(file) 9033163Sbostic char *file; 9130103Sbostic { 9251587Sbostic register u_char *p; 9333163Sbostic register short gotsp; 9451587Sbostic register int ch, len; 9551587Sbostic register u_long linect, wordct, charct; 9651587Sbostic struct stat sb; 9733163Sbostic int fd; 9833163Sbostic u_char buf[MAXBSIZE]; 9930103Sbostic 10051587Sbostic fd = STDIN_FILENO; 10130103Sbostic linect = wordct = charct = 0; 10230103Sbostic if (file) { 10351587Sbostic if ((fd = open(file, O_RDONLY, 0)) < 0) 10451587Sbostic err("%s: %s", file, strerror(errno)); 10551587Sbostic if (doword) 10651587Sbostic goto word; 10751587Sbostic /* 10851587Sbostic * Line counting is split out because it's a lot faster to get 10951587Sbostic * lines than to get words, since the word count requires some 11051587Sbostic * logic. 11151587Sbostic */ 11251587Sbostic if (doline) { 11351587Sbostic while (len = read(fd, buf, MAXBSIZE)) { 11451587Sbostic if (len == -1) 11551587Sbostic err("%s: %s", file, strerror(errno)); 11651587Sbostic charct += len; 11751587Sbostic for (p = buf; len--; ++p) 11851587Sbostic if (*p == '\n') 11951587Sbostic ++linect; 1201161Sbill } 12151587Sbostic tlinect += linect; 12251587Sbostic (void)printf(" %7lu", linect); 12330103Sbostic if (dochar) { 12451587Sbostic tcharct += charct; 12551587Sbostic (void)printf(" %7lu", charct); 1261161Sbill } 12751587Sbostic (void)close(fd); 12851587Sbostic return; 1291161Sbill } 13051587Sbostic /* 13151587Sbostic * If all we need is the number of characters and it's a 13251587Sbostic * regular or linked file, just stat the puppy. 13351587Sbostic */ 13451587Sbostic if (dochar) { 13551587Sbostic if (fstat(fd, &sb)) 13651587Sbostic err("%s: %s", file, strerror(errno)); 13751587Sbostic if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) { 138*59588Sbostic (void)printf(" %7qu", sb.st_size); 13951587Sbostic tcharct += sb.st_size; 14051587Sbostic (void)close(fd); 14151587Sbostic return; 14251587Sbostic } 14351587Sbostic } 14430103Sbostic } 14551587Sbostic 14651587Sbostic /* Do it the hard way... */ 14751587Sbostic word: for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) { 14851587Sbostic if (len == -1) 14951587Sbostic err("%s: %s", file, strerror(errno)); 15051587Sbostic /* 15151587Sbostic * This loses in the presence of multi-byte characters. 15251587Sbostic * To do it right would require a function to return a 15351587Sbostic * character while knowing how many bytes it consumed. 15451587Sbostic */ 15530103Sbostic charct += len; 15651587Sbostic for (p = buf; len--;) { 15751587Sbostic ch = *p++; 15851587Sbostic if (ch == '\n') 15951587Sbostic ++linect; 16051587Sbostic if (isspace(ch)) 16151587Sbostic gotsp = 1; 16251587Sbostic else if (gotsp) { 16351587Sbostic gotsp = 0; 16451587Sbostic ++wordct; 16530103Sbostic } 16651587Sbostic } 16730103Sbostic } 16830103Sbostic if (doline) { 1691161Sbill tlinect += linect; 17051587Sbostic (void)printf(" %7lu", linect); 17130103Sbostic } 17230103Sbostic if (doword) { 1731161Sbill twordct += wordct; 17451587Sbostic (void)printf(" %7lu", wordct); 17530103Sbostic } 17630103Sbostic if (dochar) { 1771161Sbill tcharct += charct; 17851587Sbostic (void)printf(" %7lu", charct); 1791161Sbill } 18051587Sbostic (void)close(fd); 1811161Sbill } 18251587Sbostic 18351587Sbostic void 18451587Sbostic usage() 18551587Sbostic { 18651587Sbostic (void)fprintf(stderr, "usage: wc [-clw] [files]\n"); 18751587Sbostic exit(1); 18851587Sbostic } 18951587Sbostic 19051587Sbostic #if __STDC__ 19151587Sbostic #include <stdarg.h> 19251587Sbostic #else 19351587Sbostic #include <varargs.h> 19451587Sbostic #endif 19551587Sbostic 19651587Sbostic void 19751587Sbostic #if __STDC__ 19851587Sbostic err(const char *fmt, ...) 19951587Sbostic #else 20051587Sbostic err(fmt, va_alist) 20151587Sbostic char *fmt; 20251587Sbostic va_dcl 20351587Sbostic #endif 20451587Sbostic { 20551587Sbostic va_list ap; 20651587Sbostic #if __STDC__ 20751587Sbostic va_start(ap, fmt); 20851587Sbostic #else 20951587Sbostic va_start(ap); 21051587Sbostic #endif 21151587Sbostic (void)fprintf(stderr, "wc: "); 21251587Sbostic (void)vfprintf(stderr, fmt, ap); 21351587Sbostic va_end(ap); 21451587Sbostic (void)fprintf(stderr, "\n"); 21551587Sbostic exit(1); 21651587Sbostic /* NOTREACHED */ 21751587Sbostic } 218