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