xref: /386bsd/usr/src/usr.bin/file/file.c (revision a2142627)
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