diff --git a/usr.bin/cmp/cmp.c b/usr.bin/cmp/cmp.c index 01750aa66da7..746616c0c20b 100644 --- a/usr.bin/cmp/cmp.c +++ b/usr.bin/cmp/cmp.c @@ -100,8 +100,9 @@ main(int argc, char *argv[]) int ch, fd1, fd2, oflag; bool special; const char *file1, *file2; + int ret; - limit = skip1 = skip2 = 0; + limit = skip1 = skip2 = ret = 0; oflag = O_RDONLY; while ((ch = getopt_long(argc, argv, "+bhi:ln:sxz", long_opts, NULL)) != -1) switch (ch) { @@ -199,8 +200,8 @@ main(int argc, char *argv[]) if (fd1 == -1) { if (fd2 == -1) { - c_link(file1, skip1, file2, skip2, limit); - exit(0); + ret = c_link(file1, skip1, file2, skip2, limit); + goto end; } else if (!sflag) errx(ERR_EXIT, "%s: Not a symbolic link", file2); else @@ -239,19 +240,23 @@ main(int argc, char *argv[]) #ifdef SIGINFO (void)signal(SIGINFO, siginfo); #endif - if (special) - c_special(fd1, file1, skip1, fd2, file2, skip2, limit); - else { + if (special) { + ret = c_special(fd1, file1, skip1, fd2, file2, skip2, limit); + } else { if (zflag && sb1.st_size != sb2.st_size) { if (!sflag) (void)printf("%s %s differ: size\n", file1, file2); - exit(DIFF_EXIT); + ret = DIFF_EXIT; + } else { + ret = c_regular(fd1, file1, skip1, sb1.st_size, + fd2, file2, skip2, sb2.st_size, limit); } - c_regular(fd1, file1, skip1, sb1.st_size, - fd2, file2, skip2, sb2.st_size, limit); } - exit(0); +end: + if (!sflag && fflush(stdout) != 0) + err(ERR_EXIT, "stdout"); + exit(ret); } static void diff --git a/usr.bin/cmp/extern.h b/usr.bin/cmp/extern.h index a7cb1fe5330b..4671b34653fa 100644 --- a/usr.bin/cmp/extern.h +++ b/usr.bin/cmp/extern.h @@ -34,10 +34,10 @@ #define DIFF_EXIT 1 #define ERR_EXIT 2 /* error exit code */ -void c_link(const char *, off_t, const char *, off_t, off_t); -void c_regular(int, const char *, off_t, off_t, int, const char *, off_t, +int c_link(const char *, off_t, const char *, off_t, off_t); +int c_regular(int, const char *, off_t, off_t, int, const char *, off_t, off_t, off_t); -void c_special(int, const char *, off_t, int, const char *, off_t, off_t); +int c_special(int, const char *, off_t, int, const char *, off_t, off_t); void diffmsg(const char *, const char *, off_t, off_t, int, int); void eofmsg(const char *); diff --git a/usr.bin/cmp/link.c b/usr.bin/cmp/link.c index a08f4dcf9973..dfa2f957d829 100644 --- a/usr.bin/cmp/link.c +++ b/usr.bin/cmp/link.c @@ -37,7 +37,7 @@ #include "extern.h" -void +int c_link(const char *file1, off_t skip1, const char *file2, off_t skip2, off_t limit) { @@ -87,15 +87,17 @@ c_link(const char *file1, off_t skip1, const char *file2, off_t skip2, else (void)printf("%6lld %3o %3o\n", (long long)byte, ch, *p2); - } else + } else { diffmsg(file1, file2, byte, 1, ch, *p2); - /* NOTREACHED */ + return (DIFF_EXIT); + } } byte++; } - if (*p1 || *p2) + if (*p1 || *p2) { eofmsg (*p1 ? file2 : file1); - if (dfound) - exit(DIFF_EXIT); + return (DIFF_EXIT); + } + return (dfound ? DIFF_EXIT : 0); } diff --git a/usr.bin/cmp/misc.c b/usr.bin/cmp/misc.c index 78b431b6f6a9..4abefff31cf9 100644 --- a/usr.bin/cmp/misc.c +++ b/usr.bin/cmp/misc.c @@ -43,17 +43,15 @@ eofmsg(const char *file) { if (!sflag) warnx("EOF on %s", file); - exit(DIFF_EXIT); } void diffmsg(const char *file1, const char *file2, off_t byte, off_t line, int b1, int b2) { - if (sflag) - goto out; - - if (bflag) { + if (sflag) { + /* nothing */ + } else if (bflag) { (void)printf("%s %s differ: char %lld, line %lld is %3o %c %3o %c\n", file1, file2, (long long)byte, (long long)line, b1, b1, b2, b2); @@ -61,6 +59,4 @@ diffmsg(const char *file1, const char *file2, off_t byte, off_t line, (void)printf("%s %s differ: char %lld, line %lld\n", file1, file2, (long long)byte, (long long)line); } -out: - exit(DIFF_EXIT); } diff --git a/usr.bin/cmp/regular.c b/usr.bin/cmp/regular.c index 9e1db2bd8772..c4407f708e8a 100644 --- a/usr.bin/cmp/regular.c +++ b/usr.bin/cmp/regular.c @@ -50,7 +50,7 @@ static void segv_handler(int); #define ROUNDPAGE(i) ((i) & ~pagemask) -void +int c_regular(int fd1, const char *file1, off_t skip1, off_t len1, int fd2, const char *file2, off_t skip2, off_t len2, off_t limit) { @@ -62,15 +62,19 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, size_t pagesize; int dfound; - if (skip1 > len1) + if (skip1 > len1) { eofmsg(file1); + return (DIFF_EXIT); + } len1 -= skip1; - if (skip2 > len2) + if (skip2 > len2) { eofmsg(file2); + return (DIFF_EXIT); + } len2 -= skip2; if (sflag && len1 != len2) - exit(DIFF_EXIT); + return (DIFF_EXIT); pagesize = getpagesize(); pagemask = (off_t)pagesize - 1; @@ -82,14 +86,12 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, length = MIN(length, limit); if ((m1 = remmap(NULL, fd1, off1)) == NULL) { - c_special(fd1, file1, skip1, fd2, file2, skip2, limit); - return; + return (c_special(fd1, file1, skip1, fd2, file2, skip2, limit)); } if ((m2 = remmap(NULL, fd2, off2)) == NULL) { munmap(m1, MMAP_CHUNK); - c_special(fd1, file1, skip1, fd2, file2, skip2, limit); - return; + return (c_special(fd1, file1, skip1, fd2, file2, skip2, limit)); } if (caph_rights_limit(fd1, cap_rights_init(&rights, CAP_MMAP_R)) < 0) @@ -120,21 +122,21 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, } #endif if ((ch = *p1) != *p2) { + dfound = 1; if (xflag) { - dfound = 1; (void)printf("%08llx %02x %02x\n", (long long)byte - 1, ch, *p2); } else if (lflag) { - dfound = 1; if (bflag) (void)printf("%6lld %3o %c %3o %c\n", (long long)byte, ch, ch, *p2, *p2); else (void)printf("%6lld %3o %3o\n", (long long)byte, ch, *p2); - } else + } else { diffmsg(file1, file2, byte, line, ch, *p2); - /* NOTREACHED */ + return (DIFF_EXIT); + } } if (ch == '\n') ++line; @@ -161,10 +163,11 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, if (sigaction(SIGSEGV, &oact, NULL)) err(ERR_EXIT, "sigaction()"); - if (len1 != len2) - eofmsg (len1 > len2 ? file2 : file1); - if (dfound) - exit(DIFF_EXIT); + if (len1 != len2) { + eofmsg(len1 > len2 ? file2 : file1); + return (DIFF_EXIT); + } + return (dfound ? DIFF_EXIT : 0); } static u_char * diff --git a/usr.bin/cmp/special.c b/usr.bin/cmp/special.c index 47082eb276ab..e25e82b17047 100644 --- a/usr.bin/cmp/special.c +++ b/usr.bin/cmp/special.c @@ -39,7 +39,7 @@ #include "extern.h" -void +int c_special(int fd1, const char *file1, off_t skip1, int fd2, const char *file2, off_t skip2, off_t limit) { @@ -98,7 +98,7 @@ c_special(int fd1, const char *file1, off_t skip1, (long long)byte, ch1, ch2); } else { diffmsg(file1, file2, byte, line, ch1, ch2); - /* NOTREACHED */ + return (DIFF_EXIT); } } if (ch1 == '\n') @@ -110,13 +110,17 @@ eof: if (ferror(fp1)) if (ferror(fp2)) err(ERR_EXIT, "%s", file2); if (feof(fp1)) { - if (!feof(fp2)) + if (!feof(fp2)) { eofmsg(file1); - } else - if (feof(fp2)) + return (DIFF_EXIT); + } + } else { + if (feof(fp2)) { eofmsg(file2); + return (DIFF_EXIT); + } + } fclose(fp2); fclose(fp1); - if (dfound) - exit(DIFF_EXIT); + return (dfound ? DIFF_EXIT : 0); } diff --git a/usr.bin/cmp/tests/cmp_test2.sh b/usr.bin/cmp/tests/cmp_test2.sh index 80d2e663875f..2ec6071851d3 100755 --- a/usr.bin/cmp/tests/cmp_test2.sh +++ b/usr.bin/cmp/tests/cmp_test2.sh @@ -133,6 +133,35 @@ bflag_body() cmp -bl a b } +# Helper for stdout test case +atf_check_stdout() +{ + ( + trap "" PIPE + cmp "$@" 2>stderr + echo $? >result + ) | true + atf_check -o inline:"2\n" cat result + atf_check -o match:"stdout" cat stderr +} + +atf_test_case stdout +stdout_head() +{ + atf_set descr "Failure to write to stdout" +} +stdout_body() +{ + echo a >a + echo b >b + atf_check_stdout a b + atf_check_stdout - b