version 1.17, 2007/02/19 13:02:08 |
version 1.18, 2008/05/08 01:40:56 |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/param.h> /* for MAXPATHLEN */ |
#include <sys/param.h> /* for MAXPATHLEN */ |
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <fcntl.h> /* for open() */ |
|
#ifdef RESTORE_TIME |
#ifdef RESTORE_TIME |
# if (__COHERENT__ >= 0x420) |
# if (__COHERENT__ >= 0x420) |
# include <sys/utime.h> |
# include <sys/utime.h> |
|
|
|
|
|
|
#ifdef S_IFLNK |
#ifdef S_IFLNK |
#define SYMLINKFLAG "L" |
#define SYMLINKFLAG "Lh" |
#else |
#else |
#define SYMLINKFLAG "" |
#define SYMLINKFLAG "" |
#endif |
#endif |
|
|
#define USAGE "Usage: %s [-bck" SYMLINKFLAG "Nnrsvz] [-F separator] [-f namefile] [-m magicfiles] file ...\n" \ |
# define USAGE "Usage: %s [-bck" SYMLINKFLAG "nNrsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] file...\n" \ |
" %s [-m magicfiles] -C\n" |
" %s [-m magicfiles] -C\n" |
|
|
#ifndef MAXPATHLEN |
#ifndef MAXPATHLEN |
#define MAXPATHLEN 512 |
#define MAXPATHLEN 512 |
|
|
private int /* Global command-line options */ |
private int /* Global command-line options */ |
bflag = 0, /* brief output format */ |
bflag = 0, /* brief output format */ |
nopad = 0, /* Don't pad output */ |
nopad = 0, /* Don't pad output */ |
nobuffer = 0; /* Do not buffer stdout */ |
nobuffer = 0, /* Do not buffer stdout */ |
|
nulsep = 0; /* Append '\0' to the separator */ |
|
|
private const char *magicfile = 0; /* where the magic is */ |
private const char *magicfile = 0; /* where the magic is */ |
private const char *default_magicfile = MAGIC; |
private const char *default_magicfile = MAGIC; |
private char *separator = ":"; /* Default field separator */ |
private const char *separator = ":"; /* Default field separator */ |
|
|
private char *progname; /* used throughout */ |
|
|
|
private struct magic_set *magic; |
private struct magic_set *magic; |
|
extern char *__progname; |
|
|
private void unwrap(char *); |
private void unwrap(char *); |
private void usage(void); |
private void usage(void); |
|
|
int |
int |
main(int argc, char *argv[]) |
main(int argc, char *argv[]) |
{ |
{ |
int c; |
int c, i; |
int action = 0, didsomefiles = 0, errflg = 0; |
int action = 0, didsomefiles = 0, errflg = 0; |
int flags = 0; |
int flags = 0; |
char *home, *usermagic; |
char *home, *usermagic; |
struct stat sb; |
struct stat sb; |
#define OPTSTRING "bcCdf:F:kLm:nNprsvz" |
static const char hmagic[] = "/.magic"; |
|
#define OPTSTRING "bcCde:f:F:hkLm:nNprsvz0" |
#ifdef HAVE_GETOPT_LONG |
#ifdef HAVE_GETOPT_LONG |
int longindex; |
int longindex; |
private struct option long_options[] = |
static const struct option long_options[] = |
{ |
{ |
{"version", 0, 0, 'v'}, |
{"version", 0, 0, 'v'}, |
{"help", 0, 0, 0}, |
{"help", 0, 0, 0}, |
{"brief", 0, 0, 'b'}, |
{"brief", 0, 0, 'b'}, |
{"checking-printout", 0, 0, 'c'}, |
{"checking-printout", 0, 0, 'c'}, |
{"debug", 0, 0, 'd'}, |
{"debug", 0, 0, 'd'}, |
|
{"exclude", 1, 0, 'e' }, |
{"files-from", 1, 0, 'f'}, |
{"files-from", 1, 0, 'f'}, |
{"separator", 1, 0, 'F'}, |
{"separator", 1, 0, 'F'}, |
{"keep-going", 0, 0, 'k'}, |
{"keep-going", 0, 0, 'k'}, |
#ifdef S_IFLNK |
#ifdef S_IFLNK |
{"dereference", 0, 0, 'L'}, |
{"dereference", 0, 0, 'L'}, |
|
{"no-dereference", 0, 0, 'h'}, |
#endif |
#endif |
{"magic-file", 1, 0, 'm'}, |
{"magic-file", 1, 0, 'm'}, |
#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) |
#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) |
|
|
{"no-pad", 0, 0, 'N'}, |
{"no-pad", 0, 0, 'N'}, |
{"special-files", 0, 0, 's'}, |
{"special-files", 0, 0, 's'}, |
{"compile", 0, 0, 'C'}, |
{"compile", 0, 0, 'C'}, |
|
{"print0", 0, 0, '0'}, |
{0, 0, 0, 0}, |
{0, 0, 0, 0}, |
}; |
}; |
#endif |
#endif |
|
|
|
static const struct { |
|
const char *name; |
|
int value; |
|
} nv[] = { |
|
{ "apptype", MAGIC_NO_CHECK_APPTYPE }, |
|
{ "ascii", MAGIC_NO_CHECK_ASCII }, |
|
{ "compress", MAGIC_NO_CHECK_COMPRESS }, |
|
{ "elf", MAGIC_NO_CHECK_ELF }, |
|
{ "fortran", MAGIC_NO_CHECK_FORTRAN }, |
|
{ "soft", MAGIC_NO_CHECK_SOFT }, |
|
{ "tar", MAGIC_NO_CHECK_TAR }, |
|
{ "tokens", MAGIC_NO_CHECK_TOKENS }, |
|
{ "troff", MAGIC_NO_CHECK_TROFF }, |
|
}; |
|
|
#ifdef LC_CTYPE |
#ifdef LC_CTYPE |
setlocale(LC_CTYPE, ""); /* makes islower etc work for other langs */ |
/* makes islower etc work for other langs */ |
|
(void)setlocale(LC_CTYPE, ""); |
#endif |
#endif |
|
|
#ifdef __EMX__ |
#ifdef __EMX__ |
|
|
_wildcard(&argc, &argv); |
_wildcard(&argc, &argv); |
#endif |
#endif |
|
|
if ((progname = strrchr(argv[0], '/')) != NULL) |
|
progname++; |
|
else |
|
progname = argv[0]; |
|
|
|
magicfile = default_magicfile; |
magicfile = default_magicfile; |
if ((usermagic = getenv("MAGIC")) != NULL) |
if ((usermagic = getenv("MAGIC")) != NULL) |
magicfile = usermagic; |
magicfile = usermagic; |
else |
else |
if ((home = getenv("HOME")) != NULL) { |
if ((home = getenv("HOME")) != NULL) { |
size_t len = strlen(home) + 8; |
size_t len = strlen(home) + sizeof(hmagic); |
if ((usermagic = malloc(len)) != NULL) { |
if ((usermagic = malloc(len)) != NULL) { |
(void)strlcpy(usermagic, home, len); |
(void)strlcpy(usermagic, home, len); |
(void)strlcat(usermagic, "/.magic", len); |
(void)strlcat(usermagic, hmagic, len); |
if (stat(usermagic, &sb)<0) |
if (stat(usermagic, &sb)<0) |
free(usermagic); |
free(usermagic); |
else |
else |
|
|
} |
} |
} |
} |
|
|
|
#ifdef S_IFLNK |
|
flags |= getenv("POSIXLY_CORRECT") ? MAGIC_SYMLINK : 0; |
|
#endif |
#ifndef HAVE_GETOPT_LONG |
#ifndef HAVE_GETOPT_LONG |
while ((c = getopt(argc, argv, OPTSTRING)) != -1) |
while ((c = getopt(argc, argv, OPTSTRING)) != -1) |
#else |
#else |
|
|
help(); |
help(); |
break; |
break; |
#endif |
#endif |
|
case '0': |
|
nulsep = 1; |
|
break; |
case 'b': |
case 'b': |
++bflag; |
++bflag; |
break; |
break; |
|
|
case 'd': |
case 'd': |
flags |= MAGIC_DEBUG|MAGIC_CHECK; |
flags |= MAGIC_DEBUG|MAGIC_CHECK; |
break; |
break; |
|
case 'e': |
|
for (i = 0; i < sizeof(nv) / sizeof(nv[0]); i++) |
|
if (strcmp(nv[i].name, optarg) == 0) |
|
break; |
|
|
|
if (i == sizeof(nv) / sizeof(nv[0])) |
|
errflg++; |
|
else |
|
flags |= nv[i].value; |
|
break; |
|
|
case 'f': |
case 'f': |
if(action) |
if(action) |
usage(); |
usage(); |
|
|
flags |= MAGIC_DEVICES; |
flags |= MAGIC_DEVICES; |
break; |
break; |
case 'v': |
case 'v': |
(void) fprintf(stdout, "%s-%d.%.2d\n", progname, |
(void)fprintf(stdout, "%s-%d.%.2d\n", __progname, |
FILE_VERSION_MAJOR, patchlevel); |
FILE_VERSION_MAJOR, patchlevel); |
(void) fprintf(stdout, "magic file from %s\n", |
(void)fprintf(stdout, "magic file from %s\n", |
magicfile); |
magicfile); |
return 1; |
return 1; |
case 'z': |
case 'z': |
|
|
case 'L': |
case 'L': |
flags |= MAGIC_SYMLINK; |
flags |= MAGIC_SYMLINK; |
break; |
break; |
|
case 'h': |
|
flags &= ~MAGIC_SYMLINK; |
|
break; |
#endif |
#endif |
case '?': |
case '?': |
default: |
default: |
|
|
case FILE_COMPILE: |
case FILE_COMPILE: |
magic = magic_open(flags|MAGIC_CHECK); |
magic = magic_open(flags|MAGIC_CHECK); |
if (magic == NULL) { |
if (magic == NULL) { |
(void)fprintf(stderr, "%s: %s\n", progname, |
(void)fprintf(stderr, "%s: %s\n", __progname, |
strerror(errno)); |
strerror(errno)); |
return 1; |
return 1; |
} |
} |
c = action == FILE_CHECK ? magic_check(magic, magicfile) : |
c = action == FILE_CHECK ? magic_check(magic, magicfile) : |
magic_compile(magic, magicfile); |
magic_compile(magic, magicfile); |
if (c == -1) { |
if (c == -1) { |
(void)fprintf(stderr, "%s: %s\n", progname, |
(void)fprintf(stderr, "%s: %s\n", __progname, |
magic_error(magic)); |
magic_error(magic)); |
return -1; |
return -1; |
} |
} |
|
|
process(argv[optind], wid); |
process(argv[optind], wid); |
} |
} |
|
|
|
magic_close(magic); |
return 0; |
return 0; |
} |
} |
|
|
|
|
private void |
private void |
|
/*ARGSUSED*/ |
load(const char *m, int flags) |
load(const char *m, int flags) |
{ |
{ |
if (magic) |
if (magic || m == NULL) |
return; |
return; |
magic = magic_open(flags); |
magic = magic_open(flags); |
if (magic == NULL) { |
if (magic == NULL) { |
(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno)); |
(void)fprintf(stderr, "%s: %s\n", __progname, strerror(errno)); |
exit(1); |
exit(1); |
} |
} |
if (magic_load(magic, magicfile) == -1) { |
if (magic_load(magic, magicfile) == -1) { |
(void)fprintf(stderr, "%s: %s\n", |
(void)fprintf(stderr, "%s: %s\n", |
progname, magic_error(magic)); |
__progname, magic_error(magic)); |
exit(1); |
exit(1); |
} |
} |
} |
} |
|
|
} else { |
} else { |
if ((f = fopen(fn, "r")) == NULL) { |
if ((f = fopen(fn, "r")) == NULL) { |
(void)fprintf(stderr, "%s: Cannot open `%s' (%s).\n", |
(void)fprintf(stderr, "%s: Cannot open `%s' (%s).\n", |
progname, fn, strerror(errno)); |
__progname, fn, strerror(errno)); |
exit(1); |
exit(1); |
} |
} |
|
|
while (fgets(buf, sizeof(buf), f) != NULL) { |
while (fgets(buf, sizeof(buf), f) != NULL) { |
cwid = file_mbswidth(buf) - 1; |
buf[strcspn(buf, "\n")] = '\0'; |
|
cwid = file_mbswidth(buf); |
if (cwid > wid) |
if (cwid > wid) |
wid = cwid; |
wid = cwid; |
} |
} |
|
|
} |
} |
|
|
while (fgets(buf, sizeof(buf), f) != NULL) { |
while (fgets(buf, sizeof(buf), f) != NULL) { |
buf[file_mbswidth(buf)-1] = '\0'; |
buf[strcspn(buf, "\n")] = '\0'; |
process(buf, wid); |
process(buf, wid); |
if(nobuffer) |
if(nobuffer) |
(void) fflush(stdout); |
(void)fflush(stdout); |
} |
} |
|
|
(void) fclose(f); |
(void)fclose(f); |
} |
} |
|
|
|
/* |
|
* Called for each input file on the command line (or in a list of files) |
|
*/ |
private void |
private void |
process(const char *inname, int wid) |
process(const char *inname, int wid) |
{ |
{ |
const char *type; |
const char *type; |
int std_in = strcmp(inname, "-") == 0; |
int std_in = strcmp(inname, "-") == 0; |
|
|
if (wid > 0 && !bflag) |
if (wid > 0 && !bflag) { |
(void) printf("%s%s%*s ", std_in ? "/dev/stdin" : inname, |
(void)printf("%s", std_in ? "/dev/stdin" : inname); |
separator, (int) (nopad ? 0 : (wid - file_mbswidth(inname))), ""); |
if (nulsep) |
|
(void)putc('\0', stdout); |
|
else |
|
(void)printf("%s", separator); |
|
(void)printf("%*s ", |
|
(int) (nopad ? 0 : (wid - file_mbswidth(inname))), ""); |
|
} |
|
|
type = magic_file(magic, std_in ? NULL : inname); |
type = magic_file(magic, std_in ? NULL : inname); |
if (type == NULL) |
if (type == NULL) |
printf("ERROR: %s\n", magic_error(magic)); |
(void)printf("ERROR: %s\n", magic_error(magic)); |
else |
else |
printf("%s\n", type); |
(void)printf("%s\n", type); |
} |
} |
|
|
|
|
|
|
size_t |
size_t |
file_mbswidth(const char *s) |
file_mbswidth(const char *s) |
{ |
{ |
#ifdef HAVE_WCHAR_H |
#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) |
size_t bytesconsumed, old_n, n, width = 0; |
size_t bytesconsumed, old_n, n, width = 0; |
mbstate_t state; |
mbstate_t state; |
wchar_t nextchar; |
wchar_t nextchar; |
|
|
private void |
private void |
usage(void) |
usage(void) |
{ |
{ |
(void)fprintf(stderr, USAGE, progname, progname); |
(void)fprintf(stderr, USAGE, __progname, __progname); |
#ifdef HAVE_GETOPT_LONG |
#ifdef HAVE_GETOPT_LONG |
(void)fputs("Try `file --help' for more information.\n", stderr); |
(void)fputs("Try `file --help' for more information.\n", stderr); |
#endif |
#endif |
|
|
private void |
private void |
help(void) |
help(void) |
{ |
{ |
puts( |
(void)puts( |
"Usage: file [OPTION]... [FILE]...\n" |
"Usage: file [OPTION]... [FILE]...\n" |
"Determine file type of FILEs.\n" |
"Determine file type of FILEs.\n" |
"\n" |
"\n" |
|
|
" -c, --checking-printout print the parsed form of the magic file, use in\n" |
" -c, --checking-printout print the parsed form of the magic file, use in\n" |
" conjunction with -m to debug a new magic file\n" |
" conjunction with -m to debug a new magic file\n" |
" before installing it\n" |
" before installing it\n" |
|
" -e, --exclude exclude test from the list of test to be\n" |
|
" performed for file. Valid tests are:\n" |
|
" ascii, apptype, elf, compress, soft, tar\n" |
" -f, --files-from FILE read the filenames to be examined from FILE\n" |
" -f, --files-from FILE read the filenames to be examined from FILE\n" |
" -F, --separator string use string as separator instead of `:'\n" |
" -F, --separator string use string as separator instead of `:'\n" |
" -k, --keep-going don't stop at the first match\n" |
" -k, --keep-going don't stop at the first match\n" |
|
|
" -r, --raw don't translate unprintable chars to \\ooo\n" |
" -r, --raw don't translate unprintable chars to \\ooo\n" |
" -s, --special-files treat special (block/char devices) files as\n" |
" -s, --special-files treat special (block/char devices) files as\n" |
" ordinary ones\n" |
" ordinary ones\n" |
|
"or\n" |
" --help display this help and exit\n" |
" --help display this help and exit\n" |
|
"or\n" |
" --version output version information and exit\n" |
" --version output version information and exit\n" |
|
"or\n" |
|
" -C, --compile compile file specified by -m\n" |
); |
); |
exit(0); |
exit(0); |
} |
} |