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