master xplshn/aruu / cmd / posix / cmp.c
 1/* See LICENSE file for copyright and license details. */
 2
 3
 4#include <stdio.h>
 5#include <stdlib.h>
 6#include <string.h>
 7
 8#include "util.h"
 9
10static void
11usage(void)
12{
13	enprintf(2, "usage: %s [-l | -s] file1 file2\n", argv0);
14}
15
16// ?man cmp: compare two files
17// ?man arguments: file1 file2
18// ?man compare two files byte by byte
19int
20main(int argc, char *argv[])
21{
22	FILE *fp[2];
23	size_t line = 1, n;
24	int ret = 0, lflag = 0, sflag = 0, same = 1, b[2];
25
26	ARGBEGIN {
27	// ?man -l: list in long format
28	case 'l':
29		lflag = 1;
30		break;
31	// ?man -s: silent mode or print summary
32	case 's':
33		sflag = 1;
34		break;
35	default:
36		usage();
37	} ARGEND
38
39	if (argc != 2 || (lflag && sflag))
40		usage();
41
42	for (n = 0; n < 2; n++) {
43		if (!strcmp(argv[n], "-")) {
44			argv[n] = "<stdin>";
45			fp[n] = stdin;
46		} else {
47			if (!(fp[n] = fopen(argv[n], "r"))) {
48				if (!sflag)
49					weprintf("fopen %s:", argv[n]);
50				return 2;
51			}
52		}
53	}
54
55	for (n = 1; ; n++) {
56		b[0] = getc(fp[0]);
57		b[1] = getc(fp[1]);
58
59		if (b[0] == b[1]) {
60			if (b[0] == EOF)
61				break;
62			else if (b[0] == '\n')
63				line++;
64			continue;
65		} else if (b[0] == EOF || b[1] == EOF) {
66			if (!sflag)
67				weprintf("EOF on %s\n", argv[(b[0] != EOF)]);
68			same = 0;
69			break;
70		} else if (!lflag) {
71			if (!sflag)
72				printf("%s %s differ: byte %zu, line %zu\n",
73				       argv[0], argv[1], n, line);
74			same = 0;
75			break;
76		} else {
77			printf("%zu %o %o\n", n, b[0], b[1]);
78			same = 0;
79		}
80	}
81
82	if (!ret)
83		ret = !same;
84	if (fshut(fp[0], argv[0]) | (fp[0] != fp[1] && fshut(fp[1], argv[1])) |
85	    fshut(stdout, "<stdout>"))
86		ret = 2;
87
88	return ret;
89}