xref: /386bsd/usr/src/usr.bin/file/softmagic.c (revision a2142627)
1 /*
2  * softmagic - interpret variable magic from /etc/magic
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 "file.h"
30 
31 #ifndef	lint
32 static char *moduleid =
33 	"@(#)$Header: softmagic.c,v 1.7 87/11/06 11:25:31 ian Exp $";
34 #endif	/* lint */
35 
36 extern char *progname;
37 extern char *magicfile;	/* name of current /etc/magic or clone */
38 extern int debug, nmagic;
39 extern FILE *efopen();
40 extern struct magic magic[];
41 static int magindex;
42 
43 /*
44  * softmagic - lookup one file in database
45  * (already read from /etc/magic by apprentice.c).
46  * Passed the name and FILE * of one file to be typed.
47  */
softmagic(buf)48 softmagic(buf)
49 char *buf;
50 {
51 	magindex = 0;
52 	if (match(buf))
53 		return 1;
54 
55 	return 0;
56 }
57 
58 /*
59  * go through the whole list, stopping if you find a match.
60  * Be sure to process every continuation of this match.
61  */
match(s)62 match(s)
63 char	*s;
64 {
65 	while (magindex < nmagic) {
66 		/* if main entry matches, print it... */
67 		if (mcheck(s, &magic[magindex])) {
68 			mprint(&magic[magindex],s);
69 			/* and any continuations that match */
70 			while (magic[magindex+1].contflag &&
71 				magindex < nmagic) {
72 				++magindex;
73 				if (mcheck(s, &magic[magindex])){
74 					(void) putchar(' ');
75 					mprint(&magic[magindex],s);
76 				}
77 			}
78 			return 1;		/* all through */
79 		} else {
80 			/* main entry didn't match, flush its continuations */
81 			while (magic[magindex+1].contflag &&
82 				magindex < nmagic) {
83 				++magindex;
84 			}
85 		}
86 		++magindex;			/* on to the next */
87 	}
88 	return 0;				/* no match at all */
89 }
90 
91 
92 mprint(m,s)
93 struct magic *m;
94 char *s;
95 {
96 	register union VALUETYPE *p = (union VALUETYPE *)(s+m->offset);
97 	char *pp, *strchr();
98 
99 	switch (m->type) {
100 	case BYTE:
101 		(void) printf(m->desc, p->b);
102 		break;
103 	case SHORT:
104 		(void) printf(m->desc, p->h);
105 		break;
106 	case LONG:
107 		(void) printf(m->desc, p->l);
108 		break;
109 	case STRING:
110 		if ((pp=strchr(p->s, '\n')) != NULL)
111 			*pp = '\0';
112 		(void) printf(m->desc, p->s);
113 		break;
114 	default:
115 		warning("invalid m->type (%d) in mprint()", m->type);
116 	}
117 }
118 
119 int
mcheck(s,m)120 mcheck(s, m)
121 char	*s;
122 struct magic *m;
123 {
124 	register union VALUETYPE *p = (union VALUETYPE *)(s+m->offset);
125 	register long l = m->value.l;
126 	register long v;
127 
128 	if (debug) {
129 		(void) printf("mcheck: %10.10s ", s);
130 		mdump(m);
131 	}
132 	switch (m->type) {
133 	case BYTE:
134 		v = p->b; break;
135 	case SHORT:
136 		v = p->h; break;
137 	case LONG:
138 		v = p->l; break;
139 	case STRING:
140 		l = 0;
141 		/* What we want here is:
142 		 * v = strncmp(m->value.s, p->s, m->vallen);
143 		 * but ignoring any nulls.  bcmp doesn't give -/+/0
144 		 * and isn't universally available anyway.
145 		 */
146 		{
147 			register unsigned char *a = (unsigned char*)m->value.s;
148 			register unsigned char *b = (unsigned char*)p->s;
149 			register int len = m->vallen;
150 
151 			while (--len >= 0)
152 				if ((v = *b++ - *a++) != 0)
153 					break;
154 		}
155 		break;
156 	default:
157 		warning("invalid type %d in mcheck()", m->type);
158 		return 0;
159 	}
160 
161 	switch (m->reln) {
162 	case '=':
163 		return v == l;
164 	case '>':
165 		return v > l;
166 	case '<':
167 		return v < l;
168 	case '&':
169 		return v & l;
170 	default:
171 		warning("mcheck: can't happen: invalid relation %d", m->reln);
172 		return 0;
173 	}
174 }
175