386BSD 0.1 development
[unix-history] / usr / src / usr.bin / file / softmagic.c
CommitLineData
66a734b3
WJ
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
32static char *moduleid =
33 "@(#)$Header: softmagic.c,v 1.7 87/11/06 11:25:31 ian Exp $";
34#endif /* lint */
35
36extern char *progname;
37extern char *magicfile; /* name of current /etc/magic or clone */
38extern int debug, nmagic;
39extern FILE *efopen();
40extern struct magic magic[];
41static 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 */
48softmagic(buf)
49char *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 */
62match(s)
63char *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
92mprint(m,s)
93struct magic *m;
94char *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
119int
120mcheck(s, m)
121char *s;
122struct 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}