Commit | Line | Data |
---|---|---|
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 | |
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 | */ | |
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 | */ | |
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 | |
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 | } |