diff --git a/configure.ac b/configure.ac index 1428dc893..8f50e8102 100644 --- a/configure.ac +++ b/configure.ac @@ -1501,6 +1501,18 @@ AS_IF([test "x$with_libz" = xno], [have_z=no], [ AC_CHECK_LIB([z], [crc32], [have_z=yes], [have_z=no]) ]) +AC_ARG_WITH([libmagic], + AS_HELP_STRING([--without-libmagic], [compile without libmagic]), + [], [with_libmagic=auto] +) +AS_IF([test "x$with_libmagic" = xno], [have_magic=no], [ + AC_CHECK_LIB([magic], [magic_open], [ + AC_DEFINE([HAVE_MAGIC], [1], [Define to 1 if you have the libmagic present.]) + MAGIC_LIBS="-lmagic" + ]) +]) +AC_SUBST([MAGIC_LIBS]) + AC_ARG_ENABLE([cramfs], AS_HELP_STRING([--disable-cramfs], [do not build fsck.cramfs, mkfs.cramfs]), diff --git a/text-utils/Makemodule.am b/text-utils/Makemodule.am index 3f10934e9..6c4b52082 100644 --- a/text-utils/Makemodule.am +++ b/text-utils/Makemodule.am @@ -80,7 +80,7 @@ bin_PROGRAMS += more dist_man_MANS += text-utils/more.1 more_SOURCES = text-utils/more.c more_CFLAGS = $(AM_CFLAGS) $(BSD_WARN_CFLAGS) -more_LDADD = $(LDADD) libcommon.la +more_LDADD = $(LDADD) $(MAGIC_LIBS) libcommon.la if HAVE_TINFO more_LDADD += $(TINFO_LIBS) more_LDADD += $(TINFO_CFLAGS) diff --git a/text-utils/more.c b/text-utils/more.c index 69a0b89f6..014b40a6c 100644 --- a/text-utils/more.c +++ b/text-utils/more.c @@ -74,13 +74,17 @@ # include #endif -#include "env.h" +#ifdef HAVE_MAGIC +# include +#endif + #include "strutils.h" #include "nls.h" #include "xalloc.h" #include "widechar.h" #include "closestream.h" #include "rpmatch.h" +#include "env.h" #ifdef TEST_PROGRAM # define NON_INTERACTIVE_MORE 1 @@ -157,6 +161,9 @@ struct more_control { int last_key_arg; /* previous key command argument */ int last_colon_command; /* is a colon-prefixed key command */ char *shell_line; /* line to execute in subshell */ +#ifdef HAVE_MAGIC + magic_t magic; /* libmagic database entries */ +#endif unsigned int bad_stdout:1, /* true if overwriting does not turn off standout */ catch_suspend:1, /* we should catch the SIGTSTP signal */ @@ -350,19 +357,24 @@ static void print_separator(const int c, int n) putchar('\n'); } -/* magic -- - * check for file magic numbers. This code would best be shared - * with the file(1) program or, perhaps, more should not try to be - * so smart. */ -static int check_magic(FILE *f, char *fs) +/* check_magic -- check for file magic numbers. */ +static int check_magic(struct more_control *ctl, char *fs) { +#ifdef HAVE_MAGIC + const char *mime_encoding = magic_descriptor(ctl->magic, fileno(ctl->current_file)); + + if (!mime_encoding || !(strcmp("binary", mime_encoding))) { + printf(_("\n******** %s: Not a text file ********\n\n"), fs); + return 1; + } +#else signed char twobytes[2]; /* don't try to look ahead if the input is unseekable */ - if (fseek(f, 0L, SEEK_SET)) + if (fseek(ctl->current_file, 0L, SEEK_SET)) return 0; - if (fread(twobytes, 2, 1, f) == 1) { + if (fread(twobytes, 2, 1, ctl->current_file) == 1) { switch (twobytes[0] + (twobytes[1] << 8)) { case 0407: /* a.out obj */ case 0410: /* a.out exec */ @@ -376,7 +388,8 @@ static int check_magic(FILE *f, char *fs) return 1; } } - fseek(f, 0L, SEEK_SET); /* rewind() not necessary */ + fseek(ctl->current_file, 0L, SEEK_SET); /* rewind() not necessary */ +#endif return 0; } @@ -394,23 +407,17 @@ static void checkf(struct more_control *ctl, char *fs) (fstat(fileno(ctl->current_file), &st) != 0)) { if (ctl->clear_line_ends) putp(ctl->erase_line); - warn(_("stat of %s failed"), fs); - ctl->current_file = NULL; + warn(_("cannot open %s"), fs); return; } +#ifndef HAVE_MAGIC if ((st.st_mode & S_IFMT) == S_IFDIR) { printf(_("\n*** %s: directory ***\n\n"), fs); ctl->current_file = NULL; return; } - ctl->current_line = 0; - ctl->file_position = 0; - if ((ctl->current_file = fopen(fs, "r")) == NULL) { - fflush(stdout); - warn(_("cannot open %s"), fs); - return; - } - if (check_magic(ctl->current_file, fs)) { +#endif + if (check_magic(ctl, fs)) { fclose(ctl->current_file); ctl->current_file = NULL; return; @@ -704,6 +711,9 @@ static void reset_tty(struct more_control *ctl) /* Clean up terminal state and exit. Also come here if interrupt signal received */ static void __attribute__((__noreturn__)) more_exit(struct more_control *ctl) { +#ifdef HAVE_MAGIC + magic_close(ctl->magic); +#endif reset_tty(ctl); if (ctl->clear_line_ends) { putchar('\r'); @@ -1906,6 +1916,10 @@ int main(int argc, char **argv) initterm(&ctl); +#ifdef HAVE_MAGIC + ctl.magic = magic_open(MAGIC_MIME_ENCODING | MAGIC_SYMLINK); + magic_load(ctl.magic, NULL); +#endif prepare_line_buffer(&ctl); ctl.d_scroll_len = ctl.lines_per_page / 2 - 1;