* softmagic - interpret variable magic from /etc/magic
* Copyright (c) Ian F. Darwin, 1987.
* Written by Ian F. Darwin.
* This software is not subject to any license of the American Telephone
* and Telegraph Company or of the Regents of the University of California.
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
* 1. The author is not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits must appear in the documentation.
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
"@(#)softmagic.c,v 1.2 1993/06/10 00:38:18 jtc Exp";
static int match
__P((unsigned char *));
static int mcheck
__P((unsigned char *, struct magic
*));
static void mprint
__P((struct magic
*, unsigned char *));
* softmagic - lookup one file in database
* (already read from /etc/magic by apprentice.c).
* Passed the name and FILE * of one file to be typed.
/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
* Go through the whole list, stopping if you find a match. Process all
* the continuations of that match before returning.
* We support multi-level continuations:
* At any time when processing a successful top-level match, there is a
* current continuation level; it represents the level of the last
* successfully matched continuation.
* Continuations above that level are skipped as, if we see one, it
* means that the continuation that controls them - i.e, the
* lower-level continuation preceding them - failed to match.
* Continuations below that level are processed as, if we see one,
* it means we've finished processing or skipping higher-level
* continuations under the control of a successful or unsuccessful
* lower-level continuation, and are now seeing the next lower-level
* continuation and should process it. The current continuation
* level reverts to the level of the one we're seeing.
* Continuations at the current level are processed as, if we see
* one, there's no lower-level continuation that may have failed.
* If a continuation matches, we bump the current continuation level
* so that higher-level continuations are processed.
while (magindex
< nmagic
) {
/* if main entry matches, print it... */
if (mcheck(s
, &magic
[magindex
])) {
mprint(&magic
[magindex
],s
);
* If we printed something, we'll need to print
* a blank before we print something else.
if (magic
[magindex
].desc
[0])
/* and any continuations that match */
while (magic
[magindex
+1].cont_level
!= 0 &&
magic
[magindex
].cont_level
) {
magic
[magindex
].cont_level
) {
* We're at the end of the
magic
[magindex
].cont_level
;
if (mcheck(s
, &magic
[magindex
])) {
* This continuation matched.
* Print its message, with
* the previous item printed
* and this item isn't empty.
/* space if previous printed */
&& (magic
[magindex
].nospflag
== 0)
&& (magic
[magindex
].desc
[0] != '\0')
mprint(&magic
[magindex
],s
);
if (magic
[magindex
].desc
[0])
* If we see any continuations
return 1; /* all through */
/* main entry didn't match, flush its continuation */
while (magic
[magindex
+1].cont_level
!= 0 &&
++magindex
; /* on to the next */
return 0; /* no match at all */
register union VALUETYPE
*p
= (union VALUETYPE
*)(s
+m
->offset
);
/* correct byte order dependancies */
p
->h
= (short)((p
->hs
[0]<<8)|(p
->hs
[1]));
((p
->hl
[0]<<24)|(p
->hl
[1]<<16)|(p
->hl
[2]<<8)|(p
->hl
[3]));
p
->h
= (short)((p
->hs
[1]<<8)|(p
->hs
[0]));
((p
->hl
[3]<<24)|(p
->hl
[2]<<16)|(p
->hl
[1]<<8)|(p
->hl
[0]));
(m
->reln
& MASK
) ? p
->b
& m
->mask
: p
->b
);
(m
->reln
& MASK
) ? p
->h
& m
->mask
: p
->h
);
(m
->reln
& MASK
) ? p
->l
& m
->mask
: p
->l
);
if ((rt
=strchr(p
->s
, '\n')) != NULL
)
(void) printf(m
->desc
, p
->s
);
pp
= ctime((time_t*) &p
->l
);
if ((rt
= strchr(pp
, '\n')) != NULL
)
(void) printf(m
->desc
, pp
);
error("invalid m->type (%d) in mprint().\n", m
->type
);
register union VALUETYPE
*p
= (union VALUETYPE
*)(s
+m
->offset
);
register long l
= m
->value
.l
;
register long mask
= m
->mask
;
(void) printf("mcheck: %10.10s ", s
);
if ( (m
->value
.s
[0] == 'x') && (m
->value
.s
[1] == '\0') ) {
* v = strncmp(m->value.s, p->s, m->vallen);
* but ignoring any nulls. bcmp doesn't give -/+/0
* and isn't universally available anyway.
register unsigned char *a
= (unsigned char*)m
->value
.s
;
register unsigned char *b
= (unsigned char*)p
->s
;
register int len
= m
->vallen
;
if ((v
= *b
++ - *a
++) != 0)
v
= (short)((p
->hs
[0]<<8)|(p
->hs
[1]));
((p
->hl
[0]<<24)|(p
->hl
[1]<<16)|(p
->hl
[2]<<8)|(p
->hl
[3]));
v
= (short)((p
->hs
[1]<<8)|(p
->hs
[0]));
((p
->hl
[3]<<24)|(p
->hl
[2]<<16)|(p
->hl
[1]<<8)|(p
->hl
[0]));
error("invalid type %d in mcheck().\n", m
->type
);
error("mcheck: can't happen: invalid relation %d.\n", m
->reln
);