1f0d9efc0Sbeck /*
2f0d9efc0Sbeck **	find file types by using a modified "magic" file
3f0d9efc0Sbeck **
4f0d9efc0Sbeck **	based on file v3.22 by Ian F. Darwin (see below)
5f0d9efc0Sbeck **
6f0d9efc0Sbeck **	For each entry in the magic file, the message MUST start with
7f0d9efc0Sbeck **	two 4 character strings which are the CREATOR and TYPE for the
8f0d9efc0Sbeck **	Mac file. Any continuation lines are ignored. e.g magic entry
9f0d9efc0Sbeck **	for a GIF file:
10f0d9efc0Sbeck **
11f0d9efc0Sbeck **	0       string          GIF8            8BIM GIFf
12f0d9efc0Sbeck **	>4      string          7a              \b, version 8%s,
13f0d9efc0Sbeck **	>4      string          9a              \b, version 8%s,
14f0d9efc0Sbeck **	>6      leshort         >0              %hd x
15f0d9efc0Sbeck **	>8      leshort         >0              %hd,
16f0d9efc0Sbeck **	#>10    byte            &0x80           color mapped,
17f0d9efc0Sbeck **	#>10    byte&0x07       =0x00           2 colors
18f0d9efc0Sbeck **	#>10    byte&0x07       =0x01           4 colors
19f0d9efc0Sbeck **	#>10    byte&0x07       =0x02           8 colors
20f0d9efc0Sbeck **	#>10    byte&0x07       =0x03           16 colors
21f0d9efc0Sbeck **	#>10    byte&0x07       =0x04           32 colors
22f0d9efc0Sbeck **	#>10    byte&0x07       =0x05           64 colors
23f0d9efc0Sbeck **	#>10    byte&0x07       =0x06           128 colors
24f0d9efc0Sbeck **	#>10    byte&0x07       =0x07           256 colors
25f0d9efc0Sbeck **
26f0d9efc0Sbeck **	Just the "8BIM" "GIFf" will be used whatever the type GIF file
27f0d9efc0Sbeck **	it is.
28f0d9efc0Sbeck **
29f0d9efc0Sbeck **	Modified for mkhybrid James Pearson 19/5/98
30f0d9efc0Sbeck */
31f0d9efc0Sbeck 
32f0d9efc0Sbeck /*
33f0d9efc0Sbeck  * file - find type of a file or files - main program.
34f0d9efc0Sbeck  *
35f0d9efc0Sbeck  * Copyright (c) Ian F. Darwin, 1987.
36f0d9efc0Sbeck  * Written by Ian F. Darwin.
37f0d9efc0Sbeck  *
38f0d9efc0Sbeck  * This software is not subject to any license of the American Telephone
39f0d9efc0Sbeck  * and Telegraph Company or of the Regents of the University of California.
40f0d9efc0Sbeck  *
41f0d9efc0Sbeck  * Permission is granted to anyone to use this software for any purpose on
42f0d9efc0Sbeck  * any computer system, and to alter it and redistribute it freely, subject
43f0d9efc0Sbeck  * to the following restrictions:
44f0d9efc0Sbeck  *
45f0d9efc0Sbeck  * 1. The author is not responsible for the consequences of use of this
46f0d9efc0Sbeck  *    software, no matter how awful, even if they arise from flaws in it.
47f0d9efc0Sbeck  *
48f0d9efc0Sbeck  * 2. The origin of this software must not be misrepresented, either by
49f0d9efc0Sbeck  *    explicit claim or by omission.  Since few users ever read sources,
50f0d9efc0Sbeck  *    credits must appear in the documentation.
51f0d9efc0Sbeck  *
52f0d9efc0Sbeck  * 3. Altered versions must be plainly marked as such, and must not be
53f0d9efc0Sbeck  *    misrepresented as being the original software.  Since few users
54f0d9efc0Sbeck  *    ever read sources, credits must appear in the documentation.
55f0d9efc0Sbeck  *
56f0d9efc0Sbeck  * 4. This notice may not be removed or altered.
57f0d9efc0Sbeck  */
58f0d9efc0Sbeck #include <stdio.h>
59f0d9efc0Sbeck #include <stdlib.h>
60f0d9efc0Sbeck #include <string.h>
61f0d9efc0Sbeck #include <sys/types.h>
62f0d9efc0Sbeck #include <sys/param.h>	/* for MAXPATHLEN */
63f0d9efc0Sbeck #include <sys/stat.h>
64f0d9efc0Sbeck #include <fcntl.h>	/* for open() */
65f0d9efc0Sbeck #if (__COHERENT__ >= 0x420)
66f0d9efc0Sbeck # include <sys/utime.h>
67f0d9efc0Sbeck #else
68f0d9efc0Sbeck # ifdef USE_UTIMES
69f0d9efc0Sbeck #  include <sys/time.h>
70f0d9efc0Sbeck # else
71f0d9efc0Sbeck #  include <utime.h>
72f0d9efc0Sbeck # endif
73f0d9efc0Sbeck #endif
74f0d9efc0Sbeck #include <unistd.h>	/* for read() */
75f0d9efc0Sbeck 
76f0d9efc0Sbeck #include <netinet/in.h>		/* for byte swapping */
77f0d9efc0Sbeck 
78f0d9efc0Sbeck #include "patchlevel.h"
79f0d9efc0Sbeck #include "file.h"
80*68cbdb5eSespie #include "proto.h"
81f0d9efc0Sbeck 
82f0d9efc0Sbeck int 			/* Global command-line options 		*/
83f0d9efc0Sbeck #ifdef DEBUG
84f0d9efc0Sbeck 	debug = 1, 	/* debugging 				*/
85f0d9efc0Sbeck #else
86f0d9efc0Sbeck 	debug = 0, 	/* debugging 				*/
87f0d9efc0Sbeck #endif /* DEBUG */
88f0d9efc0Sbeck 	lflag = 0,	/* follow Symlinks (BSD only) 		*/
89f0d9efc0Sbeck 	zflag = 0;	/* follow (uncompress) compressed files */
90f0d9efc0Sbeck 
91f0d9efc0Sbeck int			/* Misc globals				*/
92f0d9efc0Sbeck 	nmagic = 0;	/* number of valid magic[]s 		*/
93f0d9efc0Sbeck 
94f0d9efc0Sbeck struct  magic *magic;	/* array of magic entries		*/
95f0d9efc0Sbeck 
96f0d9efc0Sbeck char *magicfile;	/* where magic be found 		*/
97f0d9efc0Sbeck 
98f0d9efc0Sbeck char *progname;		/* used throughout 			*/
99f0d9efc0Sbeck int lineno;		/* line number in the magic file	*/
100f0d9efc0Sbeck 
101f0d9efc0Sbeck #if 0
102f0d9efc0Sbeck static int	byteconv4	__P((int, int, int));
103f0d9efc0Sbeck static short	byteconv2	__P((int, int, int));
104f0d9efc0Sbeck #endif
105f0d9efc0Sbeck 
106f0d9efc0Sbeck #if 0
107f0d9efc0Sbeck /*
108f0d9efc0Sbeck  * byteconv4
109f0d9efc0Sbeck  * Input:
110f0d9efc0Sbeck  *	from		4 byte quantity to convert
111f0d9efc0Sbeck  *	same		whether to perform byte swapping
112f0d9efc0Sbeck  *	big_endian	whether we are a big endian host
113f0d9efc0Sbeck  */
114f0d9efc0Sbeck static int
byteconv4(from,same,big_endian)115f0d9efc0Sbeck byteconv4(from, same, big_endian)
116f0d9efc0Sbeck     int from;
117f0d9efc0Sbeck     int same;
118f0d9efc0Sbeck     int big_endian;
119f0d9efc0Sbeck {
120f0d9efc0Sbeck   if (same)
121f0d9efc0Sbeck     return from;
122f0d9efc0Sbeck   else if (big_endian)		/* lsb -> msb conversion on msb */
123f0d9efc0Sbeck   {
124f0d9efc0Sbeck     union {
125f0d9efc0Sbeck       int i;
126f0d9efc0Sbeck       char c[4];
127f0d9efc0Sbeck     } retval, tmpval;
128f0d9efc0Sbeck 
129f0d9efc0Sbeck     tmpval.i = from;
130f0d9efc0Sbeck     retval.c[0] = tmpval.c[3];
131f0d9efc0Sbeck     retval.c[1] = tmpval.c[2];
132f0d9efc0Sbeck     retval.c[2] = tmpval.c[1];
133f0d9efc0Sbeck     retval.c[3] = tmpval.c[0];
134f0d9efc0Sbeck 
135f0d9efc0Sbeck     return retval.i;
136f0d9efc0Sbeck   }
137f0d9efc0Sbeck   else
138f0d9efc0Sbeck     return ntohl(from);		/* msb -> lsb conversion on lsb */
139f0d9efc0Sbeck }
140f0d9efc0Sbeck 
141f0d9efc0Sbeck /*
142f0d9efc0Sbeck  * byteconv2
143f0d9efc0Sbeck  * Same as byteconv4, but for shorts
144f0d9efc0Sbeck  */
145f0d9efc0Sbeck static short
byteconv2(from,same,big_endian)146f0d9efc0Sbeck byteconv2(from, same, big_endian)
147f0d9efc0Sbeck 	int from;
148f0d9efc0Sbeck 	int same;
149f0d9efc0Sbeck 	int big_endian;
150f0d9efc0Sbeck {
151f0d9efc0Sbeck   if (same)
152f0d9efc0Sbeck     return from;
153f0d9efc0Sbeck   else if (big_endian)		/* lsb -> msb conversion on msb */
154f0d9efc0Sbeck   {
155f0d9efc0Sbeck     union {
156f0d9efc0Sbeck       short s;
157f0d9efc0Sbeck       char c[2];
158f0d9efc0Sbeck     } retval, tmpval;
159f0d9efc0Sbeck 
160f0d9efc0Sbeck     tmpval.s = (short) from;
161f0d9efc0Sbeck     retval.c[0] = tmpval.c[1];
162f0d9efc0Sbeck     retval.c[1] = tmpval.c[0];
163f0d9efc0Sbeck 
164f0d9efc0Sbeck     return retval.s;
165f0d9efc0Sbeck   }
166f0d9efc0Sbeck   else
167f0d9efc0Sbeck     return ntohs(from);		/* msb -> lsb conversion on lsb */
168f0d9efc0Sbeck }
169f0d9efc0Sbeck #endif
170f0d9efc0Sbeck 
171f0d9efc0Sbeck /*
172f0d9efc0Sbeck  * get_magic_match - get the CREATOR/TYPE string
173f0d9efc0Sbeck  * based on the original process()
174f0d9efc0Sbeck  */
175f0d9efc0Sbeck char *
get_magic_match(inname)176f0d9efc0Sbeck get_magic_match(inname)
177f0d9efc0Sbeck const char	*inname;
178f0d9efc0Sbeck {
179f0d9efc0Sbeck 	int	fd = 0;
180f0d9efc0Sbeck 	unsigned char	buf[HOWMANY+1];	/* one extra for terminating '\0' */
181f0d9efc0Sbeck 	struct stat	sb;
182f0d9efc0Sbeck 	int nbytes = 0;	/* number of bytes read from a datafile */
183f0d9efc0Sbeck 	char *match;
184f0d9efc0Sbeck 
185f0d9efc0Sbeck 	/* check the file is regular and non-zero length */
186f0d9efc0Sbeck 	if (stat(inname, &sb) != 0)
187f0d9efc0Sbeck 		return 0;
188f0d9efc0Sbeck 
189f0d9efc0Sbeck 	if (sb.st_size == 0 || ! S_ISREG(sb.st_mode))
190f0d9efc0Sbeck 		return 0;
191f0d9efc0Sbeck 
192f0d9efc0Sbeck 	if ((fd = open(inname, O_RDONLY)) < 0)
193f0d9efc0Sbeck 		    return 0;
194f0d9efc0Sbeck 
195f0d9efc0Sbeck 	/*
196f0d9efc0Sbeck 	 * try looking at the first HOWMANY bytes
197f0d9efc0Sbeck 	 */
198f0d9efc0Sbeck 	if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1)
199f0d9efc0Sbeck 		return 0;
200f0d9efc0Sbeck 
201f0d9efc0Sbeck 	if (nbytes == 0)
202f0d9efc0Sbeck 		return 0;
203f0d9efc0Sbeck 	else {
204f0d9efc0Sbeck 		buf[nbytes++] = '\0';	/* null-terminate it */
205f0d9efc0Sbeck 		match = softmagic(buf, nbytes);
206f0d9efc0Sbeck 	}
207f0d9efc0Sbeck 
208f0d9efc0Sbeck #ifdef RESTORE_TIME
209f0d9efc0Sbeck 	/* really no point as we going to access the file later anyway */
210f0d9efc0Sbeck 	{
211f0d9efc0Sbeck 		/*
212f0d9efc0Sbeck 		 * Try to restore access, modification times if read it.
213f0d9efc0Sbeck 		 */
214f0d9efc0Sbeck # ifdef USE_UTIMES
215f0d9efc0Sbeck 		struct timeval  utsbuf[2];
216f0d9efc0Sbeck 		utsbuf[0].tv_sec = sb.st_atime;
217f0d9efc0Sbeck 		utsbuf[1].tv_sec = sb.st_mtime;
218f0d9efc0Sbeck 
219f0d9efc0Sbeck 		(void) utimes(inname, utsbuf); /* don't care if loses */
220f0d9efc0Sbeck # else
221f0d9efc0Sbeck 		struct utimbuf  utbuf;
222f0d9efc0Sbeck 
223f0d9efc0Sbeck 		utbuf.actime = sb.st_atime;
224f0d9efc0Sbeck 		utbuf.modtime = sb.st_mtime;
225f0d9efc0Sbeck 		(void) utime(inname, &utbuf); /* don't care if loses */
226f0d9efc0Sbeck # endif
227f0d9efc0Sbeck #endif
228f0d9efc0Sbeck 	(void) close(fd);
229f0d9efc0Sbeck 
230f0d9efc0Sbeck 	return(match);
231f0d9efc0Sbeck }
232f0d9efc0Sbeck 
233f0d9efc0Sbeck /*
234f0d9efc0Sbeck  * clean_magic - deallocate memory used
235f0d9efc0Sbeck  */
236f0d9efc0Sbeck void
237f0d9efc0Sbeck clean_magic()
238f0d9efc0Sbeck {
239f0d9efc0Sbeck 	if (magic)
240f0d9efc0Sbeck 		free(magic);
241f0d9efc0Sbeck }
242f0d9efc0Sbeck 
243f0d9efc0Sbeck 
244f0d9efc0Sbeck #ifdef MAIN
245f0d9efc0Sbeck main(argc, argv)
246f0d9efc0Sbeck int	argc;
247f0d9efc0Sbeck char	**argv;
248f0d9efc0Sbeck {
249f0d9efc0Sbeck 	char	*ret;
250f0d9efc0Sbeck 	char	creator[5];
251f0d9efc0Sbeck 	char	type[5];
252f0d9efc0Sbeck 
253f0d9efc0Sbeck 	if (argc < 3)
254f0d9efc0Sbeck 		exit(1);
255f0d9efc0Sbeck 
256f0d9efc0Sbeck 	init_magic(argv[1]);
257f0d9efc0Sbeck 
258f0d9efc0Sbeck 	ret = get_magic_match(argv[2]);
259f0d9efc0Sbeck 
260f0d9efc0Sbeck 	if (!ret)
261f0d9efc0Sbeck 		ret = "unixTEXT";
262f0d9efc0Sbeck 
263f0d9efc0Sbeck 	sscanf(ret, "%4s%4s", creator, type);
264f0d9efc0Sbeck 
265f0d9efc0Sbeck 	creator[4] = type[4] = '\0';
266f0d9efc0Sbeck 
267f0d9efc0Sbeck 	printf("%s %s\n", creator, type);
268f0d9efc0Sbeck 
269f0d9efc0Sbeck 
270f0d9efc0Sbeck 	exit(0);
271f0d9efc0Sbeck }
272f0d9efc0Sbeck #endif /* MAIN */
273f0d9efc0Sbeck 
274