]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/file/softmagic.c
This commit was generated by cvs2svn to compensate for changes in r104204,
[FreeBSD/FreeBSD.git] / contrib / file / softmagic.c
1 /*
2  * softmagic - interpret variable magic from 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 "file.h"
29 #include <string.h>
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include <time.h>
33 #include <regex.h>
34
35
36 #ifndef lint
37 FILE_RCSID("@(#)$Id: softmagic.c,v 1.51 2002/07/03 18:26:38 christos Exp $")
38 #endif  /* lint */
39
40 static int match(struct magic *, uint32_t, unsigned char *, int);
41 static int mget(union VALUETYPE *, unsigned char *, struct magic *, int);
42 static int mcheck(union VALUETYPE *, struct magic *);
43 static int32_t mprint(union VALUETYPE *, struct magic *);
44 static void mdebug(int32_t, char *, int);
45 static int mconvert(union VALUETYPE *, struct magic *);
46
47 extern int kflag;
48
49 /*
50  * softmagic - lookup one file in database 
51  * (already read from MAGIC by apprentice.c).
52  * Passed the name and FILE * of one file to be typed.
53  */
54 /*ARGSUSED1*/           /* nbytes passed for regularity, maybe need later */
55 int
56 softmagic(unsigned char *buf, int nbytes)
57 {
58         struct mlist *ml;
59
60         for (ml = mlist.next; ml != &mlist; ml = ml->next)
61                 if (match(ml->magic, ml->nmagic, buf, nbytes))
62                         return 1;
63
64         return 0;
65 }
66
67 /*
68  * Go through the whole list, stopping if you find a match.  Process all
69  * the continuations of that match before returning.
70  *
71  * We support multi-level continuations:
72  *
73  *      At any time when processing a successful top-level match, there is a
74  *      current continuation level; it represents the level of the last
75  *      successfully matched continuation.
76  *
77  *      Continuations above that level are skipped as, if we see one, it
78  *      means that the continuation that controls them - i.e, the
79  *      lower-level continuation preceding them - failed to match.
80  *
81  *      Continuations below that level are processed as, if we see one,
82  *      it means we've finished processing or skipping higher-level
83  *      continuations under the control of a successful or unsuccessful
84  *      lower-level continuation, and are now seeing the next lower-level
85  *      continuation and should process it.  The current continuation
86  *      level reverts to the level of the one we're seeing.
87  *
88  *      Continuations at the current level are processed as, if we see
89  *      one, there's no lower-level continuation that may have failed.
90  *
91  *      If a continuation matches, we bump the current continuation level
92  *      so that higher-level continuations are processed.
93  */
94 static int
95 match(struct magic *magic, uint32_t nmagic, unsigned char *s, int nbytes)
96 {
97         int magindex = 0;
98         int cont_level = 0;
99         int need_separator = 0;
100         union VALUETYPE p;
101         static int32_t *tmpoff = NULL;
102         static size_t tmplen = 0;
103         int32_t oldoff = 0;
104         int returnval = 0; /* if a match is found it is set to 1*/
105         int firstline = 1; /* a flag to print X\n  X\n- X */
106
107         if (tmpoff == NULL)
108                 if ((tmpoff = (int32_t *) malloc(tmplen = 20)) == NULL)
109                         error("out of memory\n");
110
111         for (magindex = 0; magindex < nmagic; magindex++) {
112                 /* if main entry matches, print it... */
113                 if (!mget(&p, s, &magic[magindex], nbytes) ||
114                     !mcheck(&p, &magic[magindex])) {
115                             /* 
116                              * main entry didn't match,
117                              * flush its continuations
118                              */
119                             while (magindex < nmagic &&
120                                    magic[magindex + 1].cont_level != 0)
121                                    magindex++;
122                             continue;
123                 }
124
125                 if (! firstline) { /* we found another match */
126                         /* put a newline and '-' to do some simple formatting*/
127                         printf("\n- ");
128                 }
129
130                 tmpoff[cont_level] = mprint(&p, &magic[magindex]);
131                 /*
132                  * If we printed something, we'll need to print
133                  * a blank before we print something else.
134                  */
135                 if (magic[magindex].desc[0])
136                         need_separator = 1;
137                 /* and any continuations that match */
138                 if (++cont_level >= tmplen)
139                         if ((tmpoff = (int32_t *) realloc(tmpoff,
140                                                        tmplen += 20)) == NULL)
141                                 error("out of memory\n");
142                 while (magic[magindex+1].cont_level != 0 && 
143                        ++magindex < nmagic) {
144                         if (cont_level >= magic[magindex].cont_level) {
145                                 if (cont_level > magic[magindex].cont_level) {
146                                         /*
147                                          * We're at the end of the level
148                                          * "cont_level" continuations.
149                                          */
150                                         cont_level = magic[magindex].cont_level;
151                                 }
152                                 if (magic[magindex].flag & OFFADD) {
153                                         oldoff=magic[magindex].offset;
154                                         magic[magindex].offset +=
155                                             tmpoff[cont_level-1];
156                                 }
157                                 if (mget(&p, s, &magic[magindex], nbytes) &&
158                                     mcheck(&p, &magic[magindex])) {
159                                         /*
160                                          * This continuation matched.
161                                          * Print its message, with
162                                          * a blank before it if
163                                          * the previous item printed
164                                          * and this item isn't empty.
165                                          */
166                                         /* space if previous printed */
167                                         if (need_separator
168                                            && (magic[magindex].nospflag == 0)
169                                            && (magic[magindex].desc[0] != '\0')
170                                            ) {
171                                                 (void) putchar(' ');
172                                                 need_separator = 0;
173                                         }
174                                         tmpoff[cont_level] =
175                                             mprint(&p, &magic[magindex]);
176                                         if (magic[magindex].desc[0])
177                                                 need_separator = 1;
178
179                                         /*
180                                          * If we see any continuations
181                                          * at a higher level,
182                                          * process them.
183                                          */
184                                         if (++cont_level >= tmplen)
185                                                 if ((tmpoff = 
186                                                     (int32_t *) realloc(tmpoff,
187                                                     tmplen += 20)) == NULL)
188                                                         error("out of memory\n");
189                                 }
190                                 if (magic[magindex].flag & OFFADD) {
191                                          magic[magindex].offset = oldoff;
192                                 }
193                         }
194                 }
195                 firstline = 0;
196                 returnval = 1;
197                 if (!kflag) {
198                         return 1; /* don't keep searching */
199                 }                       
200         }
201         return returnval;  /* This is hit if -k is set or there is no match */
202 }
203
204 static int32_t
205 mprint(union VALUETYPE *p, struct magic *m)
206 {
207         uint32_t v;
208         int32_t t=0 ;
209
210
211         switch (m->type) {
212         case BYTE:
213                 v = signextend(m, p->b);
214                 (void) printf(m->desc, (unsigned char) v);
215                 t = m->offset + sizeof(char);
216                 break;
217
218         case SHORT:
219         case BESHORT:
220         case LESHORT:
221                 v = signextend(m, p->h);
222                 (void) printf(m->desc, (unsigned short) v);
223                 t = m->offset + sizeof(short);
224                 break;
225
226         case LONG:
227         case BELONG:
228         case LELONG:
229                 v = signextend(m, p->l);
230                 (void) printf(m->desc, (uint32_t) v);
231                 t = m->offset + sizeof(int32_t);
232                 break;
233
234         case STRING:
235         case PSTRING:
236                 if (m->reln == '=') {
237                         (void) printf(m->desc, m->value.s);
238                         t = m->offset + strlen(m->value.s);
239                 }
240                 else {
241                         if (*m->value.s == '\0') {
242                                 char *cp = strchr(p->s,'\n');
243                                 if (cp)
244                                         *cp = '\0';
245                         }
246                         (void) printf(m->desc, p->s);
247                         t = m->offset + strlen(p->s);
248                 }
249                 break;
250
251         case DATE:
252         case BEDATE:
253         case LEDATE:
254                 (void) printf(m->desc, fmttime(p->l, 1));
255                 t = m->offset + sizeof(time_t);
256                 break;
257
258         case LDATE:
259         case BELDATE:
260         case LELDATE:
261                 (void) printf(m->desc, fmttime(p->l, 0));
262                 t = m->offset + sizeof(time_t);
263                 break;
264         case REGEX:
265                 (void) printf(m->desc, p->s);
266                 t = m->offset + strlen(p->s);
267                 break;
268
269         default:
270                 error("invalid m->type (%d) in mprint().\n", m->type);
271                 /*NOTREACHED*/
272         }
273         return(t);
274 }
275
276 /*
277  * Convert the byte order of the data we are looking at
278  * While we're here, let's apply the mask operation
279  * (unless you have a better idea)
280  */
281 static int
282 mconvert(union VALUETYPE *p, struct magic *m)
283 {
284         switch (m->type) {
285         case BYTE:
286                 if (m->mask)
287                         switch (m->mask_op&0x7F) {
288                         case OPAND:
289                                 p->b &= m->mask;
290                                 break;
291                         case OPOR:
292                                 p->b |= m->mask;
293                                 break;
294                         case OPXOR:
295                                 p->b ^= m->mask;
296                                 break;
297                         case OPADD:
298                                 p->b += m->mask;
299                                 break;
300                         case OPMINUS:
301                                 p->b -= m->mask;
302                                 break;
303                         case OPMULTIPLY:
304                                 p->b *= m->mask;
305                                 break;
306                         case OPDIVIDE:
307                                 p->b /= m->mask;
308                                 break;
309                         case OPMODULO:
310                                 p->b %= m->mask;
311                                 break;
312                         }
313                 if (m->mask_op & OPINVERSE)
314                         p->b = ~p->b;
315                 return 1;
316         case SHORT:
317                 if (m->mask)
318                         switch (m->mask_op&0x7F) {
319                         case OPAND:
320                                 p->h &= m->mask;
321                                 break;
322                         case OPOR:
323                                 p->h |= m->mask;
324                                 break;
325                         case OPXOR:
326                                 p->h ^= m->mask;
327                                 break;
328                         case OPADD:
329                                 p->h += m->mask;
330                                 break;
331                         case OPMINUS:
332                                 p->h -= m->mask;
333                                 break;
334                         case OPMULTIPLY:
335                                 p->h *= m->mask;
336                                 break;
337                         case OPDIVIDE:
338                                 p->h /= m->mask;
339                                 break;
340                         case OPMODULO:
341                                 p->h %= m->mask;
342                                 break;
343                         }
344                 if (m->mask_op & OPINVERSE)
345                         p->h = ~p->h;
346                 return 1;
347         case LONG:
348         case DATE:
349         case LDATE:
350                 if (m->mask)
351                         switch (m->mask_op&0x7F) {
352                         case OPAND:
353                                 p->l &= m->mask;
354                                 break;
355                         case OPOR:
356                                 p->l |= m->mask;
357                                 break;
358                         case OPXOR:
359                                 p->l ^= m->mask;
360                                 break;
361                         case OPADD:
362                                 p->l += m->mask;
363                                 break;
364                         case OPMINUS:
365                                 p->l -= m->mask;
366                                 break;
367                         case OPMULTIPLY:
368                                 p->l *= m->mask;
369                                 break;
370                         case OPDIVIDE:
371                                 p->l /= m->mask;
372                                 break;
373                         case OPMODULO:
374                                 p->l %= m->mask;
375                                 break;
376                         }
377                 if (m->mask_op & OPINVERSE)
378                         p->l = ~p->l;
379                 return 1;
380         case STRING:
381                 {
382                         int n;
383
384                         /* Null terminate and eat *trailing* return */
385                         p->s[sizeof(p->s) - 1] = '\0';
386                         n = strlen(p->s) - 1;
387                         if (p->s[n] == '\n')
388                                 p->s[n] = '\0';
389                         return 1;
390                 }
391         case PSTRING:
392                 {
393                         char *ptr1 = p->s, *ptr2 = ptr1 + 1;
394                         int n = *p->s;
395                         if (n >= sizeof(p->s))
396                                 n = sizeof(p->s) - 1;
397                         while (n--)
398                                 *ptr1++ = *ptr2++;
399                         *ptr1 = '\0';
400                         n = strlen(p->s) - 1;
401                         if (p->s[n] == '\n')
402                                 p->s[n] = '\0';
403                         return 1;
404                 }
405         case BESHORT:
406                 p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
407                 if (m->mask)
408                         switch (m->mask_op&0x7F) {
409                         case OPAND:
410                                 p->h &= m->mask;
411                                 break;
412                         case OPOR:
413                                 p->h |= m->mask;
414                                 break;
415                         case OPXOR:
416                                 p->h ^= m->mask;
417                                 break;
418                         case OPADD:
419                                 p->h += m->mask;
420                                 break;
421                         case OPMINUS:
422                                 p->h -= m->mask;
423                                 break;
424                         case OPMULTIPLY:
425                                 p->h *= m->mask;
426                                 break;
427                         case OPDIVIDE:
428                                 p->h /= m->mask;
429                                 break;
430                         case OPMODULO:
431                                 p->h %= m->mask;
432                                 break;
433                         }
434                 if (m->mask_op & OPINVERSE)
435                         p->h = ~p->h;
436                 return 1;
437         case BELONG:
438         case BEDATE:
439         case BELDATE:
440                 p->l = (int32_t)
441                     ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
442                 if (m->mask)
443                         switch (m->mask_op&0x7F) {
444                         case OPAND:
445                                 p->l &= m->mask;
446                                 break;
447                         case OPOR:
448                                 p->l |= m->mask;
449                                 break;
450                         case OPXOR:
451                                 p->l ^= m->mask;
452                                 break;
453                         case OPADD:
454                                 p->l += m->mask;
455                                 break;
456                         case OPMINUS:
457                                 p->l -= m->mask;
458                                 break;
459                         case OPMULTIPLY:
460                                 p->l *= m->mask;
461                                 break;
462                         case OPDIVIDE:
463                                 p->l /= m->mask;
464                                 break;
465                         case OPMODULO:
466                                 p->l %= m->mask;
467                                 break;
468                         }
469                 if (m->mask_op & OPINVERSE)
470                         p->l = ~p->l;
471                 return 1;
472         case LESHORT:
473                 p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
474                 if (m->mask)
475                         switch (m->mask_op&0x7F) {
476                         case OPAND:
477                                 p->h &= m->mask;
478                                 break;
479                         case OPOR:
480                                 p->h |= m->mask;
481                                 break;
482                         case OPXOR:
483                                 p->h ^= m->mask;
484                                 break;
485                         case OPADD:
486                                 p->h += m->mask;
487                                 break;
488                         case OPMINUS:
489                                 p->h -= m->mask;
490                                 break;
491                         case OPMULTIPLY:
492                                 p->h *= m->mask;
493                                 break;
494                         case OPDIVIDE:
495                                 p->h /= m->mask;
496                                 break;
497                         case OPMODULO:
498                                 p->h %= m->mask;
499                                 break;
500                         }
501                 if (m->mask_op & OPINVERSE)
502                         p->h = ~p->h;
503                 return 1;
504         case LELONG:
505         case LEDATE:
506         case LELDATE:
507                 p->l = (int32_t)
508                     ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
509                 if (m->mask)
510                         switch (m->mask_op&0x7F) {
511                         case OPAND:
512                                 p->l &= m->mask;
513                                 break;
514                         case OPOR:
515                                 p->l |= m->mask;
516                                 break;
517                         case OPXOR:
518                                 p->l ^= m->mask;
519                                 break;
520                         case OPADD:
521                                 p->l += m->mask;
522                                 break;
523                         case OPMINUS:
524                                 p->l -= m->mask;
525                                 break;
526                         case OPMULTIPLY:
527                                 p->l *= m->mask;
528                                 break;
529                         case OPDIVIDE:
530                                 p->l /= m->mask;
531                                 break;
532                         case OPMODULO:
533                                 p->l %= m->mask;
534                                 break;
535                         }
536                 if (m->mask_op & OPINVERSE)
537                         p->l = ~p->l;
538                 return 1;
539         case REGEX:
540                 return 1;
541         default:
542                 error("invalid type %d in mconvert().\n", m->type);
543                 return 0;
544         }
545 }
546
547
548 static void
549 mdebug(int32_t offset, char *str, int len)
550 {
551         (void) fprintf(stderr, "mget @%d: ", offset);
552         showstr(stderr, (char *) str, len);
553         (void) fputc('\n', stderr);
554         (void) fputc('\n', stderr);
555 }
556
557 static int
558 mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes)
559 {
560         int32_t offset = m->offset;
561
562         if (m->type == REGEX) {
563               /*
564                * offset is interpreted as last line to search,
565                * (starting at 1), not as bytes-from start-of-file
566                */
567               char *last = NULL;
568               p->buf = s;
569               for (; offset && (s = strchr(s, '\n')) != NULL; offset--, s++)
570                     last = s;
571               if (last != NULL)
572                 *last = '\0';
573         } else if (offset + sizeof(union VALUETYPE) <= nbytes)
574                 memcpy(p, s + offset, sizeof(union VALUETYPE));
575         else {
576                 /*
577                  * the usefulness of padding with zeroes eludes me, it
578                  * might even cause problems
579                  */
580                 int32_t have = nbytes - offset;
581                 memset(p, 0, sizeof(union VALUETYPE));
582                 if (have > 0)
583                         memcpy(p, s + offset, have);
584         }
585
586         if (debug) {
587                 mdebug(offset, (char *) p, sizeof(union VALUETYPE));
588                 mdump(m);
589         }
590
591         if (m->flag & INDIR) {
592                 switch (m->in_type) {
593                 case BYTE:
594                         if (m->in_offset)
595                                 switch (m->in_op&0x7F) {
596                                 case OPAND:
597                                         offset = p->b & m->in_offset;
598                                         break;
599                                 case OPOR:
600                                         offset = p->b | m->in_offset;
601                                         break;
602                                 case OPXOR:
603                                         offset = p->b ^ m->in_offset;
604                                         break;
605                                 case OPADD:
606                                         offset = p->b + m->in_offset;
607                                         break;
608                                 case OPMINUS:
609                                         offset = p->b - m->in_offset;
610                                         break;
611                                 case OPMULTIPLY:
612                                         offset = p->b * m->in_offset;
613                                         break;
614                                 case OPDIVIDE:
615                                         offset = p->b / m->in_offset;
616                                         break;
617                                 case OPMODULO:
618                                         offset = p->b % m->in_offset;
619                                         break;
620                                 }
621                         if (m->in_op & OPINVERSE)
622                                 offset = ~offset;
623                         break;
624                 case BESHORT:
625                         if (m->in_offset)
626                                 switch (m->in_op&0x7F) {
627                                 case OPAND:
628                                         offset = (short)((p->hs[0]<<8)|
629                                                          (p->hs[1])) &
630                                                  m->in_offset;
631                                         break;
632                                 case OPOR:
633                                         offset = (short)((p->hs[0]<<8)|
634                                                          (p->hs[1])) |
635                                                  m->in_offset;
636                                         break;
637                                 case OPXOR:
638                                         offset = (short)((p->hs[0]<<8)|
639                                                          (p->hs[1])) ^
640                                                  m->in_offset;
641                                         break;
642                                 case OPADD:
643                                         offset = (short)((p->hs[0]<<8)|
644                                                          (p->hs[1])) +
645                                                  m->in_offset;
646                                         break;
647                                 case OPMINUS:
648                                         offset = (short)((p->hs[0]<<8)|
649                                                          (p->hs[1])) -
650                                                  m->in_offset;
651                                         break;
652                                 case OPMULTIPLY:
653                                         offset = (short)((p->hs[0]<<8)|
654                                                          (p->hs[1])) *
655                                                  m->in_offset;
656                                         break;
657                                 case OPDIVIDE:
658                                         offset = (short)((p->hs[0]<<8)|
659                                                          (p->hs[1])) /
660                                                  m->in_offset;
661                                         break;
662                                 case OPMODULO:
663                                         offset = (short)((p->hs[0]<<8)|
664                                                          (p->hs[1])) %
665                                                  m->in_offset;
666                                         break;
667                                 }
668                         if (m->in_op & OPINVERSE)
669                                 offset = ~offset;
670                         break;
671                 case LESHORT:
672                         if (m->in_offset)
673                                 switch (m->in_op&0x7F) {
674                                 case OPAND:
675                                         offset = (short)((p->hs[1]<<8)|
676                                                          (p->hs[0])) &
677                                                  m->in_offset;
678                                         break;
679                                 case OPOR:
680                                         offset = (short)((p->hs[1]<<8)|
681                                                          (p->hs[0])) |
682                                                  m->in_offset;
683                                         break;
684                                 case OPXOR:
685                                         offset = (short)((p->hs[1]<<8)|
686                                                          (p->hs[0])) ^
687                                                  m->in_offset;
688                                         break;
689                                 case OPADD:
690                                         offset = (short)((p->hs[1]<<8)|
691                                                          (p->hs[0])) +
692                                                  m->in_offset;
693                                         break;
694                                 case OPMINUS:
695                                         offset = (short)((p->hs[1]<<8)|
696                                                          (p->hs[0])) -
697                                                  m->in_offset;
698                                         break;
699                                 case OPMULTIPLY:
700                                         offset = (short)((p->hs[1]<<8)|
701                                                          (p->hs[0])) *
702                                                  m->in_offset;
703                                         break;
704                                 case OPDIVIDE:
705                                         offset = (short)((p->hs[1]<<8)|
706                                                          (p->hs[0])) /
707                                                  m->in_offset;
708                                         break;
709                                 case OPMODULO:
710                                         offset = (short)((p->hs[1]<<8)|
711                                                          (p->hs[0])) %
712                                                  m->in_offset;
713                                         break;
714                                 }
715                         if (m->in_op & OPINVERSE)
716                                 offset = ~offset;
717                         break;
718                 case SHORT:
719                         if (m->in_offset)
720                                 switch (m->in_op&0x7F) {
721                                 case OPAND:
722                                         offset = p->h & m->in_offset;
723                                         break;
724                                 case OPOR:
725                                         offset = p->h | m->in_offset;
726                                         break;
727                                 case OPXOR:
728                                         offset = p->h ^ m->in_offset;
729                                         break;
730                                 case OPADD:
731                                         offset = p->h + m->in_offset;
732                                         break;
733                                 case OPMINUS:
734                                         offset = p->h - m->in_offset;
735                                         break;
736                                 case OPMULTIPLY:
737                                         offset = p->h * m->in_offset;
738                                         break;
739                                 case OPDIVIDE:
740                                         offset = p->h / m->in_offset;
741                                         break;
742                                 case OPMODULO:
743                                         offset = p->h % m->in_offset;
744                                         break;
745                                 }
746                         if (m->in_op & OPINVERSE)
747                                 offset = ~offset;
748                         break;
749                 case BELONG:
750                         if (m->in_offset)
751                                 switch (m->in_op&0x7F) {
752                                 case OPAND:
753                                         offset = (int32_t)((p->hl[0]<<24)|
754                                                          (p->hl[1]<<16)|
755                                                          (p->hl[2]<<8)|
756                                                          (p->hl[3])) &
757                                                  m->in_offset;
758                                         break;
759                                 case OPOR:
760                                         offset = (int32_t)((p->hl[0]<<24)|
761                                                          (p->hl[1]<<16)|
762                                                          (p->hl[2]<<8)|
763                                                          (p->hl[3])) |
764                                                  m->in_offset;
765                                         break;
766                                 case OPXOR:
767                                         offset = (int32_t)((p->hl[0]<<24)|
768                                                          (p->hl[1]<<16)|
769                                                          (p->hl[2]<<8)|
770                                                          (p->hl[3])) ^
771                                                  m->in_offset;
772                                         break;
773                                 case OPADD:
774                                         offset = (int32_t)((p->hl[0]<<24)|
775                                                          (p->hl[1]<<16)|
776                                                          (p->hl[2]<<8)|
777                                                          (p->hl[3])) +
778                                                  m->in_offset;
779                                         break;
780                                 case OPMINUS:
781                                         offset = (int32_t)((p->hl[0]<<24)|
782                                                          (p->hl[1]<<16)|
783                                                          (p->hl[2]<<8)|
784                                                          (p->hl[3])) -
785                                                  m->in_offset;
786                                         break;
787                                 case OPMULTIPLY:
788                                         offset = (int32_t)((p->hl[0]<<24)|
789                                                          (p->hl[1]<<16)|
790                                                          (p->hl[2]<<8)|
791                                                          (p->hl[3])) *
792                                                  m->in_offset;
793                                         break;
794                                 case OPDIVIDE:
795                                         offset = (int32_t)((p->hl[0]<<24)|
796                                                          (p->hl[1]<<16)|
797                                                          (p->hl[2]<<8)|
798                                                          (p->hl[3])) /
799                                                  m->in_offset;
800                                         break;
801                                 case OPMODULO:
802                                         offset = (int32_t)((p->hl[0]<<24)|
803                                                          (p->hl[1]<<16)|
804                                                          (p->hl[2]<<8)|
805                                                          (p->hl[3])) %
806                                                  m->in_offset;
807                                         break;
808                                 }
809                         if (m->in_op & OPINVERSE)
810                                 offset = ~offset;
811                         break;
812                 case LELONG:
813                         if (m->in_offset)
814                                 switch (m->in_op&0x7F) {
815                                 case OPAND:
816                                         offset = (int32_t)((p->hl[3]<<24)|
817                                                          (p->hl[2]<<16)|
818                                                          (p->hl[1]<<8)|
819                                                          (p->hl[0])) &
820                                                  m->in_offset;
821                                         break;
822                                 case OPOR:
823                                         offset = (int32_t)((p->hl[3]<<24)|
824                                                          (p->hl[2]<<16)|
825                                                          (p->hl[1]<<8)|
826                                                          (p->hl[0])) |
827                                                  m->in_offset;
828                                         break;
829                                 case OPXOR:
830                                         offset = (int32_t)((p->hl[3]<<24)|
831                                                          (p->hl[2]<<16)|
832                                                          (p->hl[1]<<8)|
833                                                          (p->hl[0])) ^
834                                                  m->in_offset;
835                                         break;
836                                 case OPADD:
837                                         offset = (int32_t)((p->hl[3]<<24)|
838                                                          (p->hl[2]<<16)|
839                                                          (p->hl[1]<<8)|
840                                                          (p->hl[0])) +
841                                                  m->in_offset;
842                                         break;
843                                 case OPMINUS:
844                                         offset = (int32_t)((p->hl[3]<<24)|
845                                                          (p->hl[2]<<16)|
846                                                          (p->hl[1]<<8)|
847                                                          (p->hl[0])) -
848                                                  m->in_offset;
849                                         break;
850                                 case OPMULTIPLY:
851                                         offset = (int32_t)((p->hl[3]<<24)|
852                                                          (p->hl[2]<<16)|
853                                                          (p->hl[1]<<8)|
854                                                          (p->hl[0])) *
855                                                  m->in_offset;
856                                         break;
857                                 case OPDIVIDE:
858                                         offset = (int32_t)((p->hl[3]<<24)|
859                                                          (p->hl[2]<<16)|
860                                                          (p->hl[1]<<8)|
861                                                          (p->hl[0])) /
862                                                  m->in_offset;
863                                         break;
864                                 case OPMODULO:
865                                         offset = (int32_t)((p->hl[3]<<24)|
866                                                          (p->hl[2]<<16)|
867                                                          (p->hl[1]<<8)|
868                                                          (p->hl[0])) %
869                                                  m->in_offset;
870                                         break;
871                                 }
872                         if (m->in_op & OPINVERSE)
873                                 offset = ~offset;
874                         break;
875                 case LONG:
876                         if (m->in_offset)
877                                 switch (m->in_op&0x7F) {
878                                 case OPAND:
879                                         offset = p->l & m->in_offset;
880                                         break;
881                                 case OPOR:
882                                         offset = p->l | m->in_offset;
883                                         break;
884                                 case OPXOR:
885                                         offset = p->l ^ m->in_offset;
886                                         break;
887                                 case OPADD:
888                                         offset = p->l + m->in_offset;
889                                         break;
890                                 case OPMINUS:
891                                         offset = p->l - m->in_offset;
892                                         break;
893                                 case OPMULTIPLY:
894                                         offset = p->l * m->in_offset;
895                                         break;
896                                 case OPDIVIDE:
897                                         offset = p->l / m->in_offset;
898                                         break;
899                                 case OPMODULO:
900                                         offset = p->l % m->in_offset;
901                                         break;
902                         /*      case TOOMANYSWITCHBLOCKS:
903                          *              ugh = p->eye % m->strain;
904                          *              rub;
905                          *      case BEER:
906                          *              off = p->tab & m->in_gest;
907                          *              sleep;
908                          */
909                                 }
910                         if (m->in_op & OPINVERSE)
911                                 offset = ~offset;
912                         break;
913                 }
914
915                 if (offset + sizeof(union VALUETYPE) > nbytes)
916                         return 0;
917
918                 memcpy(p, s + offset, sizeof(union VALUETYPE));
919
920                 if (debug) {
921                         mdebug(offset, (char *) p, sizeof(union VALUETYPE));
922                         mdump(m);
923                 }
924         }
925         if (!mconvert(p, m))
926           return 0;
927         return 1;
928 }
929
930 static int
931 mcheck(union VALUETYPE *p, struct magic *m)
932 {
933         uint32_t l = m->value.l;
934         uint32_t v;
935         int matched;
936
937         if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
938                 fprintf(stderr, "BOINK");
939                 return 1;
940         }
941
942
943         switch (m->type) {
944         case BYTE:
945                 v = p->b;
946                 break;
947
948         case SHORT:
949         case BESHORT:
950         case LESHORT:
951                 v = p->h;
952                 break;
953
954         case LONG:
955         case BELONG:
956         case LELONG:
957         case DATE:
958         case BEDATE:
959         case LEDATE:
960         case LDATE:
961         case BELDATE:
962         case LELDATE:
963                 v = p->l;
964                 break;
965
966         case STRING:
967         case PSTRING:
968         {
969                 /*
970                  * What we want here is:
971                  * v = strncmp(m->value.s, p->s, m->vallen);
972                  * but ignoring any nulls.  bcmp doesn't give -/+/0
973                  * and isn't universally available anyway.
974                  */
975                 unsigned char *a = (unsigned char*)m->value.s;
976                 unsigned char *b = (unsigned char*)p->s;
977                 int len = m->vallen;
978                 l = 0;
979                 v = 0;
980                 if (0L == m->mask) { /* normal string: do it fast */
981                         while (--len >= 0)
982                                 if ((v = *b++ - *a++) != '\0')
983                                         break; 
984                 } else { /* combine the others */
985                         while (--len >= 0) {
986                                 if ((m->mask & STRING_IGNORE_LOWERCASE) &&
987                                     islower(*a)) {
988                                         if ((v = tolower(*b++) - *a++) != '\0')
989                                                 break;
990                                 } else if ((m->mask & STRING_COMPACT_BLANK) && 
991                                     isspace(*a)) { 
992                                         a++;
993                                         if (isspace(*b++)) {
994                                                 while (isspace(*b))
995                                                         b++;
996                                         } else {
997                                                 v = 1;
998                                                 break;
999                                         }
1000                                 } else if (isspace(*a) &&
1001                                     (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
1002                                         a++;
1003                                         while (isspace(*b))
1004                                                 b++;
1005                                 } else {
1006                                         if ((v = *b++ - *a++) != '\0')
1007                                                 break;
1008                                 }
1009                         }
1010                 }
1011                 break;
1012         }
1013         case REGEX:
1014         {
1015                 int rc;
1016                 regex_t rx;
1017                 char errmsg[512];
1018
1019                 rc = regcomp(&rx, m->value.s, REG_EXTENDED|REG_NOSUB);
1020                 if (rc) {
1021                         regerror(rc, &rx, errmsg, sizeof(errmsg));
1022                         error("regex error %d, (%s)\n", rc, errmsg);
1023                 } else {
1024                         rc = regexec(&rx, p->buf, 0, 0, 0);
1025                         return !rc;
1026                 }
1027         }
1028         default:
1029                 error("invalid type %d in mcheck().\n", m->type);
1030                 return 0;/*NOTREACHED*/
1031         }
1032
1033         if(m->type != STRING && m->type != PSTRING)
1034                 v = signextend(m, v);
1035
1036         switch (m->reln) {
1037         case 'x':
1038                 if (debug)
1039                         (void) fprintf(stderr, "%u == *any* = 1\n", v);
1040                 matched = 1;
1041                 break;
1042
1043         case '!':
1044                 matched = v != l;
1045                 if (debug)
1046                         (void) fprintf(stderr, "%u != %u = %d\n",
1047                                        v, l, matched);
1048                 break;
1049
1050         case '=':
1051                 matched = v == l;
1052                 if (debug)
1053                         (void) fprintf(stderr, "%u == %u = %d\n",
1054                                        v, l, matched);
1055                 break;
1056
1057         case '>':
1058                 if (m->flag & UNSIGNED) {
1059                         matched = v > l;
1060                         if (debug)
1061                                 (void) fprintf(stderr, "%u > %u = %d\n",
1062                                                v, l, matched);
1063                 }
1064                 else {
1065                         matched = (int32_t) v > (int32_t) l;
1066                         if (debug)
1067                                 (void) fprintf(stderr, "%d > %d = %d\n",
1068                                                v, l, matched);
1069                 }
1070                 break;
1071
1072         case '<':
1073                 if (m->flag & UNSIGNED) {
1074                         matched = v < l;
1075                         if (debug)
1076                                 (void) fprintf(stderr, "%u < %u = %d\n",
1077                                                v, l, matched);
1078                 }
1079                 else {
1080                         matched = (int32_t) v < (int32_t) l;
1081                         if (debug)
1082                                 (void) fprintf(stderr, "%d < %d = %d\n",
1083                                                v, l, matched);
1084                 }
1085                 break;
1086
1087         case '&':
1088                 matched = (v & l) == l;
1089                 if (debug)
1090                         (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
1091                                        v, l, l, matched);
1092                 break;
1093
1094         case '^':
1095                 matched = (v & l) != l;
1096                 if (debug)
1097                         (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
1098                                        v, l, l, matched);
1099                 break;
1100
1101         default:
1102                 matched = 0;
1103                 error("mcheck: can't happen: invalid relation %d.\n", m->reln);
1104                 break;/*NOTREACHED*/
1105         }
1106
1107         return matched;
1108 }