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

file/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;   /* Do not buffer stdout */
00055 
00056 /*
00057  * unwrap -- read a file of filenames, do each one.
00058  */
00059 /*@-bounds@*/
00060 static void
00061 unwrap(fmagic fm, char *fn)
00062         /*@globals fileSystem, internalState @*/
00063         /*@modifies fm, fileSystem, internalState @*/
00064 {
00065         char buf[MAXPATHLEN];
00066         FILE *f;
00067         int wid = 0, cwid;
00068         int xx;
00069 
00070         if (strcmp("-", fn) == 0) {
00071                 f = stdin;
00072                 wid = 1;
00073         } else {
00074                 if ((f = fopen(fn, "r")) == NULL) {
00075                         error(EXIT_FAILURE, 0, "Cannot open `%s' (%s).\n", fn, strerror(errno));
00076                         /*@notreached@*/
00077                 }
00078 
00079                 while (fgets(buf, sizeof(buf), f) != NULL) {
00080                         cwid = strlen(buf) - 1;
00081                         if (cwid > wid)
00082                                 wid = cwid;
00083                 }
00084 
00085                 rewind(f);
00086         }
00087 
00088 /*@-nullpass@*/ /* LCL: buf is null??? */
00089         while (fgets(buf, sizeof(buf), f) != NULL)
00090 /*@=nullpass@*/
00091         {
00092                 buf[strlen(buf)-1] = '\0';
00093                 fm->obp = fm->obuf;
00094                 *fm->obp = '\0';
00095                 fm->nob = sizeof(fm->obuf);
00096                 xx = fmagicProcess(fm, buf, wid);
00097                 fprintf(stdout, "%s\n", fm->obuf);
00098                 if (nobuffer)
00099                         (void) fflush(stdout);
00100         }
00101 
00102         (void) fclose(f);
00103 }
00104 /*@=bounds@*/
00105 
00106 /*@exits@*/
00107 static void
00108 usage(void)
00109         /*@globals fileSystem @*/
00110         /*@modifies fileSystem @*/
00111 {
00112         (void)fprintf(stderr, USAGE, __progname);
00113         (void)fprintf(stderr, "Usage: %s -C [-m magic]\n", __progname);
00114 #ifdef HAVE_GETOPT_H
00115         (void)fputs("Try `file --help' for more information.\n", stderr);
00116 #endif
00117         exit(EXIT_FAILURE);
00118 }
00119 
00120 #ifdef HAVE_GETOPT_H
00121 /*@exits@*/
00122 static void
00123 help(void)
00124         /*@globals fileSystem @*/
00125         /*@modifies fileSystem @*/
00126 {
00127         (void) puts(
00128 "Usage: file [OPTION]... [FILE]...\n"
00129 "Determine file type of FILEs.\n"
00130 "\n"
00131 "  -m, --magic-file LIST      use LIST as a colon-separated list of magic\n"
00132 "                               number files\n"
00133 "  -z, --uncompress           try to look inside compressed files\n"
00134 "  -b, --brief                do not prepend filenames to output lines\n"
00135 "  -c, --checking-printout    print the parsed form of the magic file, use in\n"
00136 "                               conjunction with -m to debug a new magic file\n"
00137 "                               before installing it\n"
00138 "  -f, --files-from FILE      read the filenames to be examined from FILE\n"
00139 "  -i, --mime                 output mime type strings\n"
00140 "  -k, --keep-going           don't stop at the first match\n"
00141 "  -L, --dereference          causes symlinks to be followed\n"
00142 "  -n, --no-buffer            do not buffer output\n"
00143 "  -s, --special-files        treat special (block/char devices) files as\n"
00144 "                             ordinary ones\n"
00145 "      --help                 display this help and exit\n"
00146 "      --version              output version information and exit\n"
00147 );
00148         exit(0);
00149 }
00150 #endif
00151 
00152 /*
00153  * main - parse arguments and handle options
00154  */
00155 /*@-bounds@*/
00156 int
00157 main(int argc, char **argv)
00158         /*@globals global_fmagic, nobuffer,
00159                 default_magicfile, optind,
00160                 fileSystem, internalState @*/
00161         /*@modifies global_fmagic, nobuffer,
00162                 default_magicfile, optind,
00163                 fileSystem, internalState @*/
00164 {
00165         int xx;
00166         int c;
00167         int action = 0, didsomefiles = 0, errflg = 0, ret = 0, app = 0;
00168         char *mime, *home, *usermagic;
00169         fmagic fm = global_fmagic;
00170         struct stat sb;
00171 #define OPTSTRING       "bcdf:ikm:nsvzCL"
00172 #ifdef HAVE_GETOPT_H
00173         int longindex = 0;
00174 /*@-nullassign -readonlytrans@*/
00175         static struct option long_options[] =
00176         {
00177                 {"version", 0, 0, 'v'},
00178                 {"help", 0, 0, 0},
00179                 {"brief", 0, 0, 'b'},
00180                 {"checking-printout", 0, 0, 'c'},
00181                 {"debug", 0, 0, 'd'},
00182                 {"files-from", 1, 0, 'f'},
00183                 {"mime", 0, 0, 'i'},
00184                 {"keep-going", 0, 0, 'k'},
00185 #ifdef S_IFLNK
00186                 {"dereference", 0, 0, 'L'},
00187 #endif
00188                 {"magic-file", 1, 0, 'm'},
00189                 {"uncompress", 0, 0, 'z'},
00190                 {"no-buffer", 0, 0, 'n'},
00191                 {"special-files", 0, 0, 's'},
00192                 {"compile", 0, 0, 'C'},
00193                 {0, 0, 0, 0},
00194         };
00195 /*@=nullassign =readonlytrans@*/
00196 #endif
00197 
00198 #if HAVE_MCHECK_H && HAVE_MTRACE
00199         /*@-noeffect@*/
00200         mtrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
00201         /*@=noeffect@*/
00202 #endif
00203 
00204 #ifdef LC_CTYPE
00205         setlocale(LC_CTYPE, ""); /* makes islower etc work for other langs */
00206 #endif
00207 
00208 #ifdef __EMX__
00209         /* sh-like wildcard expansion! Shouldn't hurt at least ... */
00210         _wildcard(&argc, &argv);
00211 #endif
00212 
00213 /*@-assignexpose@*/
00214         fm->magicfile = default_magicfile;
00215 /*@=assignexpose@*/
00216         if ((usermagic = getenv("MAGIC")) != NULL)
00217                 fm->magicfile = usermagic;
00218         else {
00219                 if ((home = getenv("HOME")) != NULL) {
00220                         size_t nb = strlen(home) + 8;
00221                         usermagic = xmalloc(nb);
00222                         (void)strcpy(usermagic, home);
00223                         (void)strcat(usermagic, "/.magic");
00224                         if (stat(usermagic, &sb)<0) 
00225                                 free(usermagic);
00226                         else
00227                                 fm->magicfile = usermagic;
00228                 }
00229         }
00230 
00231 #ifndef HAVE_GETOPT_H
00232         while ((c = getopt(argc, argv, OPTSTRING)) != -1)
00233 #else
00234         while ((c = getopt_long(argc, argv, OPTSTRING, long_options,
00235             &longindex)) != -1)
00236 #endif
00237         {
00238                 switch (c) {
00239 #ifdef HAVE_GETOPT_H
00240                 case 0 :
00241                         if (longindex == 1)
00242                                 help();
00243                         /*@switchbreak@*/ break;
00244 #endif
00245                 case 'b':
00246                         fm->flags |= FMAGIC_FLAGS_BRIEF;
00247                         /*@switchbreak@*/ break;
00248                 case 'c':
00249                         action = CHECK;
00250                         /*@switchbreak@*/ break;
00251                 case 'C':
00252                         action = COMPILE;
00253                         /*@switchbreak@*/ break;
00254                 case 'd':
00255                         fm->flags |= FMAGIC_FLAGS_DEBUG;
00256                         /*@switchbreak@*/ break;
00257                 case 'f':
00258                         if (!app) {
00259                                 ret = fmagicSetup(fm, fm->magicfile, action);
00260                                 if (action)
00261                                         exit(ret);
00262                                 app = 1;
00263                         }
00264                         unwrap(fm, optarg);
00265                         ++didsomefiles;
00266                         /*@switchbreak@*/ break;
00267                 case 'i':
00268                         fm->flags |= FMAGIC_FLAGS_MIME;
00269                         mime = malloc(strlen(fm->magicfile) + sizeof(".mime"));
00270                         if (mime != NULL) {
00271                                 (void)strcpy(mime, fm->magicfile);
00272                                 (void)strcat(mime, ".mime");
00273                         }
00274                         fm->magicfile = mime;
00275                         /*@switchbreak@*/ break;
00276                 case 'k':
00277                         fm->flags |= FMAGIC_FLAGS_CONTINUE;
00278                         /*@switchbreak@*/ break;
00279                 case 'm':
00280 /*@-assignexpose@*/
00281                         fm->magicfile = optarg;
00282 /*@=assignexpose@*/
00283                         /*@switchbreak@*/ break;
00284                 case 'n':
00285                         ++nobuffer;
00286                         /*@switchbreak@*/ break;
00287                 case 's':
00288                         fm->flags |= FMAGIC_FLAGS_SPECIAL;
00289                         /*@switchbreak@*/ break;
00290                 case 'v':
00291                         (void) fprintf(stdout, "%s-%d.%d\n", __progname,
00292                                        FILE_VERSION_MAJOR, patchlevel);
00293                         (void) fprintf(stdout, "magic file from %s\n",
00294                                        fm->magicfile);
00295                         return 1;
00296                 case 'z':
00297                         fm->flags |= FMAGIC_FLAGS_UNCOMPRESS;
00298                         /*@switchbreak@*/ break;
00299 #ifdef S_IFLNK
00300                 case 'L':
00301                         fm->flags |= FMAGIC_FLAGS_FOLLOW;
00302                         /*@switchbreak@*/ break;
00303 #endif
00304                 case '?':
00305                 default:
00306                         errflg++;
00307                         /*@switchbreak@*/ break;
00308                 }
00309         }
00310 
00311         if (errflg)
00312                 usage();
00313 
00314         if (!app) {
00315 /*@-nullpass@*/ /* FIX: fm->magicfile may be null */
00316                 ret = fmagicSetup(fm, fm->magicfile, action);
00317 /*@=nullpass@*/
00318                 if (action)
00319                         exit(ret);
00320                 app = 1;
00321         }
00322 
00323         if (optind == argc) {
00324                 if (!didsomefiles)
00325                         usage();
00326         } else {
00327                 int i, wid, nw;
00328                 for (wid = 0, i = optind; i < argc; i++) {
00329                         nw = strlen(argv[i]);
00330                         if (nw > wid)
00331                                 wid = nw;
00332                 }
00333                 for (; optind < argc; optind++) {
00334                         fm->obp = fm->obuf;
00335                         *fm->obp = '\0';
00336                         fm->nob = sizeof(fm->obuf);
00337                         xx = fmagicProcess(fm, argv[optind], wid);
00338                         fprintf(stdout, "%s\n", fm->obuf);
00339                         if (nobuffer)
00340                                 (void) fflush(stdout);
00341                 }
00342         }
00343 
00344 #if HAVE_MCHECK_H && HAVE_MTRACE
00345         /*@-noeffect@*/
00346         muntrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
00347         /*@=noeffect@*/
00348 #endif
00349 
00350         return 0;
00351 }
00352 /*@=bounds@*/

Generated on Sun Oct 26 13:01:58 2003 for rpm by doxygen1.2.18