+static
+cmp()
+{
+ register u_char *C1, /* traveling pointers */
+ *C2;
+ register int cnt, /* counter */
+ len1, /* read length 1 */
+ len2; /* read length 2 */
+ register long byte, /* byte count */
+ line; /* line count */
+ short dfound = NO; /* if difference found */
+
+ for (byte = 0,line = 1;;) {
+ switch(len1 = read(fd1,buf1,MAXBSIZE)) {
+ case -1:
+ if (!silent)
+ perror(file1);
+ exit(ERR);
+ case 0:
+ /*
+ * read of file 1 just failed, find out
+ * if there's anything left in file 2
+ */
+ switch(read(fd2,buf2,1)) {
+ case -1:
+ if (!silent)
+ perror(file2);
+ exit(ERR);
+ case 0:
+ exit(dfound ? DIFF : OK);
+ default:
+ if (!silent)
+ printf("cmp: EOF on %s\n",file1);
+ exit(DIFF);
+ }
+ }
+ /*
+ * file1 might be stdio, which means that a read of less than
+ * MAXBSIZE might not mean an EOF. So, read whatever we read
+ * from file1 from file2.
+ */
+ if ((len2 = read(fd2,buf2,len1)) == -1) {
+ if (!silent)
+ perror(file2);
+ exit(ERR);
+ }
+ if (bcmp(buf1,buf2,len2)) {
+ if (silent)
+ exit(DIFF);
+ if (all) {
+ dfound = YES;
+ for (C1 = buf1,C2 = buf2,cnt = len2;cnt--;++C1,++C2) {
+ ++byte;
+ if (*C1 != *C2)
+ printf("%6ld %3o %3o\n",byte,*C1,*C2);
+ }
+ }
+ else
+ for (C1 = buf1,C2 = buf2;;++C1,++C2) {
+ ++byte;
+ if (*C1 != *C2) {
+ printf("%s %s differ: char %ld, line %ld\n",file1,file2,byte,line);
+ exit(DIFF);
+ }
+ if (*C1 == '\n')
+ ++line;
+ }
+ }
+ else {
+ byte += len2;
+ /*
+ * here's the real performance problem, we've got to
+ * count the stupid lines, which means that -l is a
+ * *much* faster version, i.e., unless you really
+ * *want* to know the line number, run -sl.
+ */
+ if (!all)
+ for (C1 = buf1,cnt = len2;cnt--;)
+ if (*C1++ == '\n')
+ ++line;
+ }
+ /*
+ * couldn't read as much from file2 as from file1; checked
+ * here because there might be a difference before we got
+ * to this point, which would have precedence.
+ */
+ if (len2 < len1) {
+ if (!silent)
+ printf("cmp: EOF on %s\n",file2);
+ exit(DIFF);