Annotation of 43BSDReno/usr.bin/cmp/cmp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1987 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: char copyright[] =
                     22: "@(#) Copyright (c) 1987, 1990 Regents of the University of California.\n\
                     23:  All rights reserved.\n";
                     24: #endif /* not lint */
                     25: 
                     26: #ifndef lint
                     27: static char sccsid[] = "@(#)cmp.c      5.3 (Berkeley) 6/1/90";
                     28: #endif /* not lint */
                     29: 
                     30: #include <sys/param.h>
                     31: #include <sys/file.h>
                     32: #include <sys/stat.h>
                     33: #include <stdio.h>
                     34: #include <ctype.h>
                     35: #include <errno.h>
                     36: 
                     37: #define        EXITNODIFF      0
                     38: #define        EXITDIFF        1
                     39: #define        EXITERR         2
                     40: 
                     41: int    all, fd1, fd2, silent;
                     42: u_char buf1[MAXBSIZE], buf2[MAXBSIZE];
                     43: char   *file1, *file2;
                     44: 
                     45: main(argc, argv)
                     46:        int argc;
                     47:        char *argv[];
                     48: {
                     49:        extern char *optarg;
                     50:        extern int optind;
                     51:        int ch;
                     52:        u_long otoi();
                     53: 
                     54:        while ((ch = getopt(argc, argv, "-ls")) != EOF)
                     55:                switch (ch) {
                     56:                case 'l':               /* print all differences */
                     57:                        all = 1;
                     58:                        break;
                     59:                case 's':               /* silent run */
                     60:                        silent = 1;
                     61:                        break;
                     62:                case '-':               /* must be after any flags */
                     63:                        --optind;
                     64:                        goto endargs;
                     65:                case '?':
                     66:                default:
                     67:                        usage();
                     68:                }
                     69: endargs:
                     70:        argv += optind;
                     71:        argc -= optind;
                     72: 
                     73:        if (argc < 2 || argc > 4)
                     74:                usage();
                     75: 
                     76:        if (all && silent) {
                     77:                fprintf(stderr,
                     78:                    "cmp: only one of -l and -s may be specified.\n");
                     79:                exit(EXITERR);
                     80:        }
                     81:        if (strcmp(file1 = argv[0], "-") == 0)
                     82:                fd1 = 0;
                     83:        else if ((fd1 = open(file1, O_RDONLY, 0)) < 0)
                     84:                error(file1);
                     85:        if (strcmp(file2 = argv[1], "-") == 0)
                     86:                fd2 = 0;
                     87:        else if ((fd2 = open(file2, O_RDONLY, 0)) < 0)
                     88:                error(file2);
                     89:        if (fd1 == fd2) {
                     90:                fprintf(stderr,
                     91:                    "cmp: standard input may only be specified once.\n");
                     92:                exit(EXITERR);
                     93:        }
                     94: 
                     95:        /* handle skip arguments */
                     96:        if (argc > 2) {
                     97:                skip(otoi(argv[2]), fd1, file1);
                     98:                if (argc == 4)
                     99:                        skip(otoi(argv[3]), fd2, file2);
                    100:        }
                    101:        cmp();
                    102:        /*NOTREACHED*/
                    103: }
                    104: 
                    105: /*
                    106:  * skip --
                    107:  *     skip first part of file
                    108:  */
                    109: skip(dist, fd, fname)
                    110:        register u_long dist;
                    111:        register int fd;
                    112:        char *fname;
                    113: {
                    114:        register int rlen, nread;
                    115: 
                    116:        for (; dist; dist -= rlen) {
                    117:                rlen = MIN(dist, sizeof(buf1));
                    118:                if ((nread = read(fd, buf1, rlen)) != rlen) {
                    119:                        if (nread < 0)
                    120:                                error(fname);
                    121:                        else
                    122:                                endoffile(fname);
                    123:                }
                    124:        }
                    125: }
                    126: 
                    127: cmp()
                    128: {
                    129:        register u_char *p1, *p2;
                    130:        register int cnt, len1, len2;
                    131:        register long byte, line;
                    132:        int dfound = 0;
                    133: 
                    134:        for (byte = 0, line = 1; ; ) {
                    135:                switch (len1 = read(fd1, buf1, MAXBSIZE)) {
                    136:                case -1:
                    137:                        error(file1);
                    138:                case 0:
                    139:                        /*
                    140:                         * read of file 1 just failed, find out
                    141:                         * if there's anything left in file 2
                    142:                         */
                    143:                        switch (read(fd2, buf2, 1)) {
                    144:                                case -1:
                    145:                                        error(file2);
                    146:                                        /* NOTREACHED */
                    147:                                case 0:
                    148:                                        exit(dfound ? EXITDIFF : EXITNODIFF);
                    149:                                        /* NOTREACHED */
                    150:                                default:
                    151:                                        endoffile(file1);
                    152:                                        break;
                    153:                        }
                    154:                }
                    155:                /*
                    156:                 * file1 might be stdio, which means that a read of less than
                    157:                 * MAXBSIZE might not mean an EOF.  So, read whatever we read
                    158:                 * from file1 from file2.
                    159:                 */
                    160:                if ((len2 = read(fd2, buf2, len1)) == -1)
                    161:                        error(file2);
                    162:                if (bcmp(buf1, buf2, len2)) {
                    163:                        if (silent)
                    164:                                exit(EXITDIFF);
                    165:                        if (all) {
                    166:                                dfound = 1;
                    167:                                for (p1 = buf1, p2 = buf2, cnt = len2; cnt--;
                    168:                                    ++p1, ++p2) {
                    169:                                        ++byte;
                    170:                                        if (*p1 != *p2)
                    171:                                                printf("%6ld %3o %3o\n",
                    172:                                                    byte, *p1, *p2);
                    173:                                }
                    174:                        } else for (p1 = buf1, p2 = buf2; ; ++p1, ++p2) {
                    175:                                ++byte;
                    176:                                if (*p1 != *p2) {
                    177:                                        printf("%s %s differ: char %ld, line %ld\n", file1, file2, byte, line);
                    178:                                        exit(EXITDIFF);
                    179:                                }
                    180:                                if (*p1 == '\n')
                    181:                                        ++line;
                    182:                        }
                    183:                } else {
                    184:                        byte += len2;
                    185:                        /*
                    186:                         * here's the real performance problem, we've got to
                    187:                         * count the stupid lines, which means that -l is a
                    188:                         * *much* faster version, i.e., unless you really
                    189:                         * *want* to know the line number, run -s or -l.
                    190:                         */
                    191:                        if (!silent && !all)
                    192:                                for (p1 = buf1, cnt = len2; cnt--; )
                    193:                                        if (*p1++ == '\n')
                    194:                                                ++line;
                    195:                }
                    196:                /*
                    197:                 * couldn't read as much from file2 as from file1; checked
                    198:                 * here because there might be a difference before we got
                    199:                 * to this point, which would have precedence.
                    200:                 */
                    201:                if (len2 < len1)
                    202:                        endoffile(file2);
                    203:        }
                    204: }
                    205: 
                    206: /*
                    207:  * otoi --
                    208:  *     octal/decimal string to u_long
                    209:  */
                    210: u_long
                    211: otoi(s)
                    212:        register char *s;
                    213: {
                    214:        register u_long val;
                    215:        register int base;
                    216: 
                    217:        base = (*s == '0') ? 8 : 10;
                    218:        for (val = 0; isdigit(*s); ++s)
                    219:                val = val * base + *s - '0';
                    220:        return (val);
                    221: }
                    222: 
                    223: /*
                    224:  * error --
                    225:  *     print I/O error message and die
                    226:  */
                    227: error(filename)
                    228:        char *filename;
                    229: {
                    230:        extern int errno;
                    231:        char *strerror();
                    232: 
                    233:        if (!silent)
                    234:                (void) fprintf(stderr, "cmp: %s: %s\n",
                    235:                    filename, strerror(errno));
                    236:        exit(EXITERR);
                    237: }
                    238: 
                    239: /*
                    240:  * endoffile --
                    241:  *     print end-of-file message and exit indicating the files were different
                    242:  */
                    243: endoffile(filename)
                    244:        char *filename;
                    245: {
                    246:        /* 32V put this message on stdout, S5 does it on stderr. */
                    247:        /* POSIX.2 currently does it on stdout-- Hooray! */
                    248:        if (!silent)
                    249:                (void) printf("cmp: EOF on %s\n", filename);
                    250:        exit(EXITDIFF);
                    251: }
                    252: 
                    253: /*
                    254:  * usage --
                    255:  *     print usage and die
                    256:  */
                    257: usage()
                    258: {
                    259:        fputs("usage: cmp [-ls] file1 file2 [skip1] [skip2]\n", stderr);
                    260:        exit(EXITERR);
                    261: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.