extern void bb_xprint_and_close_file(FILE *file) { bb_xfflush_stdout(); /* Note: Do not use STDOUT_FILENO here, as this is a lib routine * and the calling code may have reassigned stdout. */ if (bb_copyfd_eof(fileno(file), STDOUT_FILENO) == -1) { /* bb_copyfd outputs any needed messages, so just die. */ exit(bb_default_error_retval); } /* Note: Since we're reading, don't bother checking the return value * of fclose(). The only possible failure is EINTR which * should already have been taken care of. */ fclose(file); }
int cmp_main(int argc, char **argv) { FILE *fp1, *fp2, *outfile = stdout; const char *filename1, *filename2; const char *fmt; int c1, c2, char_pos, line_pos; int opt_flags; int exit_val = 0; bb_default_error_retval = 2; /* 1 is returned if files are different. */ opt_flags = bb_getopt_ulflags(argc, argv, opt_chars); if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) { bb_show_usage(); } fp1 = cmp_xfopen_input(filename1 = *(argv += optind)); filename2 = "-"; if (*++argv) { filename2 = *argv; } fp2 = cmp_xfopen_input(filename2); if (fp1 == fp2) { /* Paranioa check... stdin == stdin? */ /* Note that we don't bother reading stdin. Neither does gnu wc. * But perhaps we should, so that other apps down the chain don't * get the input. Consider 'echo hello | (cmp - - && cat -)'. */ return 0; } fmt = fmt_differ; if (opt_flags == OPT_l) { fmt = fmt_l_opt; } char_pos = 0; line_pos = 1; do { c1 = getc(fp1); c2 = getc(fp2); ++char_pos; if (c1 != c2) { /* Remember -- a read error may have occurred. */ exit_val = 1; /* But assume the files are different for now. */ if (c2 == EOF) { /* We know that fp1 isn't at EOF or in an error state. But to * save space below, things are setup to expect an EOF in fp1 * if an EOF occurred. So, swap things around. */ fp1 = fp2; filename1 = filename2; c1 = c2; } if (c1 == EOF) { bb_xferror(fp1, filename1); fmt = fmt_eof; /* Well, no error, so it must really be EOF. */ outfile = stderr; /* There may have been output to stdout (option -l), so * make sure we fflush before writing to stderr. */ bb_xfflush_stdout(); } if (opt_flags != OPT_s) { if (opt_flags == OPT_l) { line_pos = c1; /* line_pos is unused in the -l case. */ } bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2); if (opt_flags) { /* This must be -l since not -s. */ /* If we encountered and EOF, the while check will catch it. */ continue; } } break; } if (c1 == '\n') { ++line_pos; } } while (c1 != EOF); bb_xferror(fp1, filename1); bb_xferror(fp2, filename2); bb_fflush_stdout_and_exit(exit_val); }