* apprentice - make one pass through /etc/magic, learning its secrets.
* 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.
"@(#)$Header: apprentice.c,v 1.8 87/11/06 21:14:34 ian Exp $";
#define EATAB {while (isascii(*l) && isspace(*l)) ++l;}
extern int debug
; /* option */
extern int nmagic
; /* number of valid magic[]s */
struct magic magic
[MAXMAGIS
];
char *fn
; /* name of magic file */
int check
; /* non-zero: checking-only run. */
(void) fprintf(stderr
, "%s: can't read magic file %s\n",
if (check
) /* print silly verbose header for USG compat. */
(void) printf("cont\toffset\ttype\topcode\tvalue\tdesc\n");
while (fgets(line
, MAXSTR
, f
) != NULL
) {
if (line
[0]=='#') /* comment, do not parse */
if (strlen(line
) <= 1) /* null line, garbage, etc */
line
[strlen(line
)-1] = '\0'; /* delete newline */
if (parse(line
, &nmagic
, check
) != 0)
* parse one line from magic file, put into magic[index++] if valid
* TODO malloc the magic structures (linked list?) so this can't happen
"magic table overflow - increase MAXMAGIS beyond %d in file/apprentice.c\n",
/* get offset, then skip over it */
while (isascii(*l
) && isdigit(*l
))
if (strncmp(l
, "byte", NBYTE
)==0) {
} else if (strncmp(l
, "short", NSHORT
)==0) {
} else if (strncmp(l
, "long", NLONG
)==0) {
} else if (strncmp(l
, "string", NSTRING
)==0) {
warning("type %s invalid", l
);
if (*l
== '>' || *l
== '<' || *l
== '&' || *l
== '=') {
* TODO finish this macro and start using it!
* #define offsetcheck {if (offset > HOWMANY-1) warning("offset too big"); }
* Do not remove the casts below. They are vital.
* When later compared with the data, the sign extension must
m
->value
.l
= (char) strtol(l
,&l
,0);
m
->value
.l
= (short) strtol(l
,&l
,0);
m
->value
.l
= (long) strtol(l
,&l
,0);
l
= getstr(l
, m
->value
.s
, sizeof(m
->value
.s
), &slen
);
warning("can't happen: m->type=%d\n", m
->type
);
* now get last part - the description
while ((m
->desc
[i
++] = *l
++) != '\0' && i
<MAXDESC
)
++(*ndx
); /* make room for next */
* Convert a string containing C character escapes. Stop at an unescaped
* Copy the converted version to "p", returning its length in *slen.
* Return updated scan pointer as function result.
char *origs
= s
, *origp
= p
;
char *pmax
= p
+ plen
- 1;
while((c
= *s
++) != '\0') {
fprintf(stderr
, "String too long: %s\n", origs
);
/* \ and up to 3 octal digits */
c
= *s
++; /* try for 2 */
if(c
>= '0' && c
<= '7') {
val
= (val
<<3) | (c
- '0');
c
= *s
++; /* try for 3 */
val
= (val
<<3) | (c
-'0');
/* \x and up to 3 hex digits */
val
= 'x'; /* Default if no digits */
c
= hextoint(*s
++); /* Get next char */
/* Single hex char to int; -1 if not a hex char. */
if (!isascii(c
)) return -1;
if (isdigit(c
)) return c
- '0';
if ((c
>='a')&(c
<='f')) return c
+ 10 - 'a';
if ((c
>='A')&(c
<='F')) return c
+ 10 - 'A';
* Print a string containing C character escapes.
while((c
= *s
++) != '\0') {
if(c
>= 040 && c
<= 0176)
printf("%.3o", c
& 0377);