1 /*
2 * file - find type of a file or files - main program.
3 *
4 * Copyright (c) Ian F. Darwin, 1987.
5 * Written by Ian F. Darwin.
6 *
7 * This software is not subject to any license of the American Telephone
8 * and Telegraph Company or of the Regents of the University of California.
9 *
10 * Permission is granted to anyone to use this software for any purpose on
11 * any computer system, and to alter it and redistribute it freely, subject
12 * to the following restrictions:
13 *
14 * 1. The author is not responsible for the consequences of use of this
15 * software, no matter how awful, even if they arise from flaws in it.
16 *
17 * 2. The origin of this software must not be misrepresented, either by
18 * explicit claim or by omission. Since few users ever read sources,
19 * credits must appear in the documentation.
20 *
21 * 3. Altered versions must be plainly marked as such, and must not be
22 * misrepresented as being the original software. Since few users
23 * ever read sources, credits must appear in the documentation.
24 *
25 * 4. This notice may not be removed or altered.
26 */
27
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include "file.h"
32
33 #define USAGE "usage: %s [-c] [-f namefile] [-m magicfile] file...\n"
34
35 #ifndef lint
36 static char *moduleid =
37 "@(#)$Header: file.c,v 1.14 87/11/12 13:11:06 ian Exp $";
38 #endif /* lint */
39 extern char *ckfmsg;
40 int debug = 0, /* huh? */
41 nbytes = 0, /* number of bytes read from a datafile */
42 nmagic = 0; /* number of valid magic[]s */
43 FILE *efopen();
44 #ifdef MAGIC
45 char *magicfile = MAGIC; /* where magic be found */
46 #else
47 char *magicfile = "/etc/magic"; /* where magic be found */
48 #endif
49 char *progname;
50 struct stat statbuf;
51 struct utimbuf { /* for utime(2), belongs in a .h file */
52 time_t actime; /* access time */
53 time_t modtime; /* modification time */
54 };
55
56 /*
57 * main - parse arguments and handle options
58 */
main(argc,argv)59 main(argc, argv)
60 int argc;
61 char *argv[];
62 {
63 int c;
64 int check = 0, didsomefiles = 0, errflg = 0, ret = 0;
65 extern int optind;
66 extern char *optarg;
67
68 progname = argv[0];
69
70 while ((c = getopt(argc, argv, "cdf:m:")) != EOF)
71 switch (c) {
72 case 'c':
73 ++check;
74 break;
75 case 'd':
76 ++debug;
77 break;
78 case 'f':
79 unwrap(optarg);
80 ++didsomefiles;
81 break;
82 case 'm':
83 magicfile = optarg;
84 break;
85 case '?':
86 default:
87 errflg++;
88 break;
89 }
90 if (errflg) {
91 (void) fprintf(stderr, USAGE, progname);
92 exit(2);
93 }
94
95 ret = apprentice(magicfile, check);
96 if (check)
97 exit(ret);
98
99 if (optind == argc) {
100 if (!didsomefiles)
101 (void)fprintf(stderr, USAGE, progname);
102 }
103 else
104 for (; optind < argc; optind++)
105 process(argv[optind]);
106
107 exit(0);
108 }
109
110 /*
111 * unwrap -- read a file of filenames, do each one.
112 */
unwrap(fn)113 unwrap(fn)
114 char *fn;
115 {
116 #define FILENAMELEN 128
117 char buf[FILENAMELEN];
118 FILE *f;
119
120 if ((f = fopen(fn, "r")) == NULL)
121 (void) fprintf(stderr, "%s: file %s unreadable\n",
122 progname, fn);
123 else {
124 while (fgets(buf, FILENAMELEN, f) != NULL) {
125 buf[strlen(buf)-1] = '\0';
126 process(buf);
127 }
128 (void) fclose(f);
129 }
130 }
131
132 /*
133 * process - process input file
134 */
process(inname)135 process(inname)
136 char *inname;
137 {
138 int fd;
139 char buf[HOWMANY];
140 struct utimbuf utbuf;
141
142 if (strcmp("-", inname) == 0) {
143 (void) printf("standard input:\t");
144 if (fstat(0, &statbuf)<0)
145 warning("cannot fstat; ");
146 fd = 0;
147 goto readit;
148 }
149
150 (void) printf("%s:\t", inname);
151
152 /*
153 * first try judging the file based on its filesystem status
154 * Side effect: fsmagic updates global data `statbuf'.
155 */
156 if (fsmagic(inname) != 0) {
157 /*NULLBODY*/;
158 } else if ((fd = open(inname, 0)) < 0) {
159 /* We can't open it, but we were able to stat it. */
160 if (statbuf.st_mode & 0002) ckfputs("writeable, ", stdout);
161 if (statbuf.st_mode & 0111) ckfputs("executable, ", stdout);
162 warning("can't read");
163 } else {
164 readit:
165 /*
166 * try looking at the first HOWMANY bytes
167 */
168 if ((nbytes = read(fd, buf, HOWMANY)) == -1)
169 warning("read failed");
170 if (nbytes == 0) {
171 ckfputs("empty", stdout);
172 } else
173 /*
174 * try tests in /etc/magic (or surrogate magic file)
175 */
176 if (softmagic(buf) == 1)
177 /*NULLBODY*/;
178 else if (ascmagic(buf) == 1)
179 /*
180 * try known keywords, check for ascii-ness too.
181 */
182 /*NULLBODY*/;
183 else {
184 /*
185 * abandon hope, all ye who remain here
186 */
187 ckfputs("data", stdout);
188 }
189 if (strcmp("-", inname) != 0) {
190 /*
191 * Restore access, modification times if we read it.
192 */
193 utbuf.actime = statbuf.st_atime;
194 utbuf.modtime = statbuf.st_mtime;
195 (void) utime(inname, &utbuf);
196 /* we don't care if we lack perms */
197 (void) close(fd);
198 }
199 }
200
201 (void) putchar('\n');
202 }
203
204
205