2 * cmp.c - compare two files
5 * Build: c89 -o cmp cmp.c
6 * Source: <http://pdcore.sourceforge.net/>
7 * Spec: <http://www.opengroup.org/onlinepubs/9699919799/utilities/cmp.html>
9 * This is free and unencumbered software released into the public domain,
10 * provided "as is", without warranty of any kind, express or implied. See the
11 * file UNLICENSE and the website <http://unlicense.org> for further details.
23 #include <sys/types.h>
26 #define USAGE "usage: cmp [-l|-s] file1 file2\n"
27 #define ELSMUTEXCL "Options -l and -s are mutually exclusive"
28 #define EBOTHSTDIN "Input files must be different"
33 static int cmpfiles(int fd1, char *fn1, int fd2, char *fn2);
34 static void fatal(int errtype, char *s);
36 static int optl, opts;
39 int main(int argc, char **argv)
41 extern int opterr, optind;
42 int c, exitstatus = 0;
46 setlocale(LC_ALL, "");
49 while ((c = getopt(argc, argv, "ls")) != -1)
59 fprintf(stderr, USAGE);
67 fatal(APPERR, ELSMUTEXCL);
73 if (strcmp(fn1, "-") == 0)
76 if ((fd1 = open(fn1, O_RDONLY)) == -1)
80 if (strcmp(fn2, "-") == 0)
83 if ((fd2 = open(fn2, O_RDONLY)) == -1)
86 if (fd1 == STDIN_FILENO && fd2 == STDIN_FILENO)
87 fatal(APPERR, EBOTHSTDIN);
89 exitstatus = cmpfiles(fd1, fn1, fd2, fn2);
91 if (fd1 != STDIN_FILENO && (close(fd1) == -1))
94 if (fd2 != STDIN_FILENO && (close(fd2) == -1))
101 int cmpfiles(int fd1, char *fn1, int fd2, char *fn2)
103 unsigned char buf1[BUFSIZE], buf2[BUFSIZE];
104 ssize_t n1, n2, byte = 1, line = 1;
105 int cnt, i, eof = 0, differ = 0, shorter = 0;
109 if ((n1 = read(fd1, buf1, BUFSIZE)) == -1)
112 if ((n2 = read(fd2, buf2, BUFSIZE)) == -1)
115 if (n1 != BUFSIZE || n2 != BUFSIZE)
119 shorter = (n1 < n2) ? 1 : 2;
122 cnt = (n1 < n2) ? n1 : n2;
123 for (i = 0; i < cnt; i++)
125 if (buf1[i] != buf2[i])
127 if (! differ && ! optl && ! opts)
129 printf("%s %s differ: char %d, line %d\n", fn1, fn2, byte, line);
130 return(1); /* only need to report first mismatch */
136 printf("%d %o %o\n", byte, buf1[i], buf2[i]);
145 if (shorter && (optl || (! opts && ! differ)))
148 fprintf(stderr, "cmp: EOF on %s\n", (shorter == 1 ? fn1 : fn2));
151 return(differ || shorter);
155 void fatal(int errtype, char *s)
157 if (errtype == SYSERR)
158 fprintf(stderr, "cmp: %s: %s\n", s, strerror(errno));
160 fprintf(stderr, "cmp: %s\n", s);