Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

file.c

Go to the documentation of this file.
00001 /*
00002  * file - find type of a file or files - main program.
00003  *
00004  * Copyright (c) Ian F. Darwin, 1987.
00005  * Written by Ian F. Darwin.
00006  *
00007  * This software is not subject to any license of the American Telephone
00008  * and Telegraph Company or of the Regents of the University of California.
00009  *
00010  * Permission is granted to anyone to use this software for any purpose on
00011  * any computer system, and to alter it and redistribute it freely, subject
00012  * to the following restrictions:
00013  *
00014  * 1. The author is not responsible for the consequences of use of this
00015  *    software, no matter how awful, even if they arise from flaws in it.
00016  *
00017  * 2. The origin of this software must not be misrepresented, either by
00018  *    explicit claim or by omission.  Since few users ever read sources,
00019  *    credits must appear in the documentation.
00020  *
00021  * 3. Altered versions must be plainly marked as such, and must not be
00022  *    misrepresented as being the original software.  Since few users
00023  *    ever read sources, credits must appear in the documentation.
00024  *
00025  * 4. This notice may not be removed or altered.
00026  */
00027 
00028 #include "system.h"
00029 #include "file.h"
00030 #include "patchlevel.h"
00031 #include "debug.h"
00032 
00033 FILE_RCSID("@(#)Id: file.c,v 1.66 2002/07/03 19:00:41 christos Exp ")
00034 
00035 /*@access fmagic @*/
00036 
00037 #ifdef S_IFLNK
00038 # define USAGE  "Usage: %s [-bciknsvzL] [-f namefile] [-m magicfiles] file...\n"
00039 #else
00040 # define USAGE  "Usage: %s [-bciknsvz] [-f namefile] [-m magicfiles] file...\n"
00041 #endif
00042 
00043 #ifdef __EMX__
00044 static char *apptypeName = NULL;
00045 int os2_apptype (const char *fn, char *buf, int nb);
00046 #endif /* __EMX__ */
00047 
00048 #ifndef MAXPATHLEN
00049 #define MAXPATHLEN      512
00050 #endif
00051 
00052                         /* Global command-line options          */
00053 /*@unchecked@*/
00054 static  int     nobuffer = 0;   /* Don't buffer stdout */
00055 
00056 /*@unchecked@*/ /*@observer@*/
00057 static const char * default_separator = ":";
00058 
00059 /*
00060  * unwrap -- read a file of filenames, do each one.
00061  */
00062 /*@-bounds@*/
00063 static void
00064 unwrap(fmagic fm, char *fn)
00065         /*@globals fileSystem, internalState @*/
00066         /*@modifies fm, fileSystem, internalState @*/
00067 {
00068         char buf[MAXPATHLEN];
00069         FILE *f;
00070         int wid = 0, cwid;
00071         int xx;
00072 
00073         if (strcmp("-", fn) == 0) {
00074                 f = stdin;
00075                 wid = 1;
00076         } else {
00077                 if ((f = fopen(fn, "r")) == NULL) {
00078                         error(EXIT_FAILURE, 0, "Cannot open `%s' (%s).\n", fn, strerror(errno));
00079                         /*@notreached@*/
00080                 }
00081 
00082                 while (fgets(buf, sizeof(buf), f) != NULL) {
00083                         cwid = strlen(buf) - 1;
00084                         if (cwid > wid)
00085                                 wid = cwid;
00086                 }
00087 
00088                 rewind(f);
00089         }
00090 
00091 /*@-nullpass@*/ /* LCL: buf is null??? */
00092         while (fgets(buf, sizeof(buf), f) != NULL)
00093 /*@=nullpass@*/
00094         {
00095                 buf[strlen(buf)-1] = '\0';
00096                 fm->obp = fm->obuf;
00097                 *fm->obp = '\0';
00098                 fm->nob = sizeof(fm->obuf);
00099                 xx = fmagicProcess(fm, buf, wid);
00100                 fprintf(stdout, "%s\n", fm->obuf);
00101                 if (nobuffer)
00102                         (void) fflush(stdout);
00103         }
00104 
00105         (void) fclose(f);
00106 }
00107 /*@=bounds@*/
00108 
00109 /*@exits@*/
00110 static void
00111 usage(void)
00112         /*@globals fileSystem @*/
00113         /*@modifies fileSystem @*/
00114 {
00115         (void)fprintf(stderr, USAGE, __progname);
00116         (void)fprintf(stderr, "Usage: %s -C [-m magic]\n", __progname);
00117 #ifdef HAVE_GETOPT_H
00118         (void)fputs("Try `file --help' for more information.\n", stderr);
00119 #endif
00120         exit(EXIT_FAILURE);
00121 }
00122 
00123 #ifdef HAVE_GETOPT_H
00124 /*@exits@*/
00125 static void
00126 help(void)
00127         /*@globals fileSystem @*/
00128         /*@modifies fileSystem @*/
00129 {
00130         (void) puts(
00131 "Usage: file [OPTION]... [FILE]...\n"
00132 "Determine file type of FILEs.\n"
00133 "\n"
00134 "  -m, --magic-file LIST      use LIST as a colon-separated list of magic\n"
00135 "                               number files\n"
00136 "  -z, --uncompress           try to look inside compressed files\n"
00137 "  -b, --brief                do not prepend filenames to output lines\n"
00138 "  -c, --checking-printout    print the parsed form of the magic file, use in\n"
00139 "                               conjunction with -m to debug a new magic file\n"
00140 "                               before installing it\n"
00141 "  -f, --files-from FILE      read the filenames to be examined from FILE\n"
00142 "  -F, --separator string     use string as separator instead of `:'\n"
00143 "  -i, --mime                 output mime type strings\n"
00144 "  -k, --keep-going           don't stop at the first match\n"
00145 "  -L, --dereference          causes symlinks to be followed\n"
00146 "  -n, --no-buffer            do not buffer output\n"
00147 "  -N, --no-pad               do not pad output\n"
00148 "  -s, --special-files        treat special (block/char devices) files as\n"
00149 "                             ordinary ones\n"
00150 "      --help                 display this help and exit\n"
00151 "      --version              output version information and exit\n"
00152 );
00153         exit(0);
00154 }
00155 #endif
00156 
00157 /*
00158  * main - parse arguments and handle options
00159  */
00160 /*@-bounds@*/
00161 int
00162 main(int argc, char **argv)
00163         /*@globals global_fmagic, nobuffer,
00164                 default_magicfile, default_separator, optind,
00165                 fileSystem, internalState @*/
00166         /*@modifies global_fmagic, nobuffer,
00167                 default_magicfile, default_separator, optind,
00168                 fileSystem, internalState @*/
00169 {
00170         int xx;
00171         int c;
00172         int action = 0, didsomefiles = 0, errflg = 0, ret = 0, app = 0;
00173         char *mime, *home, *usermagic;
00174         fmagic fm = global_fmagic;
00175         struct stat sb;
00176 #define OPTSTRING       "bcdf:ikm:nsvzCL"
00177 #ifdef HAVE_GETOPT_H
00178         int longindex = 0;
00179 /*@-nullassign -readonlytrans@*/
00180         static struct option long_options[] =
00181         {
00182                 {"version", 0, 0, 'v'},
00183                 {"help", 0, 0, 0},
00184                 {"brief", 0, 0, 'b'},
00185                 {"checking-printout", 0, 0, 'c'},
00186                 {"debug", 0, 0, 'd'},
00187                 {"files-from", 1, 0, 'f'},
00188                 {"separator", 1, 0, 'F'},
00189                 {"mime", 0, 0, 'i'},
00190                 {"keep-going", 0, 0, 'k'},
00191 #ifdef S_IFLNK
00192                 {"dereference", 0, 0, 'L'},
00193 #endif
00194                 {"magic-file", 1, 0, 'm'},
00195                 {"uncompress", 0, 0, 'z'},
00196                 {"no-buffer", 0, 0, 'n'},
00197                 {"no-pad", 0, 0, 'N'},
00198                 {"special-files", 0, 0, 's'},
00199                 {"compile", 0, 0, 'C'},
00200                 {0, 0, 0, 0},
00201         };
00202 /*@=nullassign =readonlytrans@*/
00203 #endif
00204 
00205 #if HAVE_MCHECK_H && HAVE_MTRACE
00206         /*@-noeffect@*/
00207         mtrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
00208         /*@=noeffect@*/
00209 #endif
00210 
00211 #ifdef LC_CTYPE
00212         setlocale(LC_CTYPE, ""); /* makes islower etc work for other langs */
00213 #endif
00214 
00215 #ifdef __EMX__
00216         /* sh-like wildcard expansion! Shouldn't hurt at least ... */
00217         _wildcard(&argc, &argv);
00218 #endif
00219 
00220 /*@-assignexpose@*/
00221         fm->magicfile = default_magicfile;
00222         fm->separator = default_separator;
00223 /*@=assignexpose@*/
00224         if ((usermagic = getenv("MAGIC")) != NULL)
00225                 fm->magicfile = usermagic;
00226         else {
00227                 if ((home = getenv("HOME")) != NULL) {
00228                         size_t nb = strlen(home) + 8;
00229                         usermagic = xmalloc(nb);
00230                         (void)strcpy(usermagic, home);
00231                         (void)strcat(usermagic, "/.magic");
00232                         if (stat(usermagic, &sb)<0) 
00233                                 free(usermagic);
00234                         else
00235                                 fm->magicfile = usermagic;
00236                 }
00237         }
00238 
00239 #ifndef HAVE_GETOPT_H
00240         while ((c = getopt(argc, argv, OPTSTRING)) != -1)
00241 #else
00242         while ((c = getopt_long(argc, argv, OPTSTRING, long_options,
00243             &longindex)) != -1)
00244 #endif
00245         {
00246                 switch (c) {
00247 #ifdef HAVE_GETOPT_H
00248                 case 0 :
00249                         if (longindex == 1)
00250                                 help();
00251                         /*@switchbreak@*/ break;
00252 #endif
00253                 case 'b':
00254                         fm->flags |= FMAGIC_FLAGS_BRIEF;
00255                         /*@switchbreak@*/ break;
00256                 case 'c':
00257                         action = FILE_CHECK;
00258                         /*@switchbreak@*/ break;
00259                 case 'C':
00260                         action = FILE_COMPILE;
00261                         /*@switchbreak@*/ break;
00262                 case 'd':
00263                         fm->flags |= FMAGIC_FLAGS_DEBUG;
00264                         /*@switchbreak@*/ break;
00265                 case 'f':
00266                         if (!app) {
00267                                 ret = fmagicSetup(fm, fm->magicfile, action);
00268                                 if (action)
00269                                         exit(ret);
00270                                 app = 1;
00271                         }
00272                         unwrap(fm, optarg);
00273                         ++didsomefiles;
00274                         /*@switchbreak@*/ break;
00275                 case 'F':
00276 /*@-assignexpose@*/
00277                         fm->separator = optarg;
00278 /*@=assignexpose@*/
00279                         /*@switchbreak@*/ break;
00280                 case 'i':
00281                         fm->flags |= FMAGIC_FLAGS_MIME;
00282                         mime = malloc(strlen(fm->magicfile) + sizeof(".mime"));
00283                         if (mime != NULL) {
00284                                 (void)strcpy(mime, fm->magicfile);
00285                                 (void)strcat(mime, ".mime");
00286                         }
00287                         fm->magicfile = mime;
00288                         /*@switchbreak@*/ break;
00289                 case 'k':
00290                         fm->flags |= FMAGIC_FLAGS_CONTINUE;
00291                         /*@switchbreak@*/ break;
00292                 case 'm':
00293 /*@-assignexpose@*/
00294                         fm->magicfile = optarg;
00295 /*@=assignexpose@*/
00296                         /*@switchbreak@*/ break;
00297                 case 'n':
00298                         ++nobuffer;
00299                         /*@switchbreak@*/ break;
00300                 case 'N':
00301                         fm->flags |= FMAGIC_FLAGS_NOPAD;
00302                         /*@switchbreak@*/ break;
00303                 case 's':
00304                         fm->flags |= FMAGIC_FLAGS_SPECIAL;
00305                         /*@switchbreak@*/ break;
00306                 case 'v':
00307                         (void) fprintf(stdout, "%s-%d.%d\n", __progname,
00308                                        FILE_VERSION_MAJOR, patchlevel);
00309                         (void) fprintf(stdout, "magic file from %s\n",
00310                                        fm->magicfile);
00311                         return 1;
00312                 case 'z':
00313                         fm->flags |= FMAGIC_FLAGS_UNCOMPRESS;
00314                         /*@switchbreak@*/ break;
00315 #ifdef S_IFLNK
00316                 case 'L':
00317                         fm->flags |= FMAGIC_FLAGS_FOLLOW;
00318                         /*@switchbreak@*/ break;
00319 #endif
00320                 case '?':
00321                 default:
00322                         errflg++;
00323                         /*@switchbreak@*/ break;
00324                 }
00325         }
00326 
00327         if (errflg)
00328                 usage();
00329 
00330         if (!app) {
00331 /*@-nullpass@*/ /* FIX: fm->magicfile may be null */
00332                 ret = fmagicSetup(fm, fm->magicfile, action);
00333 /*@=nullpass@*/
00334                 if (action)
00335                         exit(ret);
00336                 app = 1;
00337         }
00338 
00339         if (optind == argc) {
00340                 if (!didsomefiles)
00341                         usage();
00342         } else {
00343                 int i, wid, nw;
00344                 for (wid = 0, i = optind; i < argc; i++) {
00345                         nw = strlen(argv[i]);
00346                         if (nw > wid)
00347                                 wid = nw;
00348                 }
00349                 for (; optind < argc; optind++) {
00350                         fm->obp = fm->obuf;
00351                         *fm->obp = '\0';
00352                         fm->nob = sizeof(fm->obuf);
00353                         xx = fmagicProcess(fm, argv[optind], wid);
00354                         fprintf(stdout, "%s\n", fm->obuf);
00355                         if (nobuffer)
00356                                 (void) fflush(stdout);
00357                 }
00358         }
00359 
00360 #if HAVE_MCHECK_H && HAVE_MTRACE
00361         /*@-noeffect@*/
00362         muntrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
00363         /*@=noeffect@*/
00364 #endif
00365 
00366         return 0;
00367 }
00368 /*@=bounds@*/

Generated on Thu Aug 14 14:16:36 2008 for rpm by  doxygen 1.3.9.1