]>
git.saurik.com Git - apple/file_cmds.git/blob - file/apprentice.c
435a3d8dd846d0cfff8769b6f8fc7298fdfe18e1
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* $OpenBSD: apprentice.c,v 1.4 1997/02/09 23:58:16 millert Exp $ */
27 * apprentice - make one pass through /etc/magic, learning its secrets.
29 * Copyright (c) Ian F. Darwin, 1987.
30 * Written by Ian F. Darwin.
32 * This software is not subject to any license of the American Telephone
33 * and Telegraph Company or of the Regents of the University of California.
35 * Permission is granted to anyone to use this software for any purpose on
36 * any computer system, and to alter it and redistribute it freely, subject
37 * to the following restrictions:
39 * 1. The author is not responsible for the consequences of use of this
40 * software, no matter how awful, even if they arise from flaws in it.
42 * 2. The origin of this software must not be misrepresented, either by
43 * explicit claim or by omission. Since few users ever read sources,
44 * credits must appear in the documentation.
46 * 3. Altered versions must be plainly marked as such, and must not be
47 * misrepresented as being the original software. Since few users
48 * ever read sources, credits must appear in the documentation.
50 * 4. This notice may not be removed or altered.
62 static char *moduleid
= "$OpenBSD: apprentice.c,v 1.4 1997/02/09 23:58:16 millert Exp $";
66 #define EATAB {while (isascii((unsigned char) *l) && \
67 isspace((unsigned char) *l)) ++l;}
68 #define LOWCASE(l) (isupper((unsigned char) (l)) ? \
69 tolower((unsigned char) (l)) : (l))
72 static int getvalue
__P((struct magic
*, char **));
73 static int hextoint
__P((int));
74 static char *getstr
__P((char *, char *, int, int *));
75 static int parse
__P((char *, int *, int));
76 static void eatsize
__P((char **));
78 static int maxmagic
= 0;
80 static int apprentice_1
__P((char *, int));
84 char *fn
; /* list of magic files */
85 int check
; /* non-zero? checking-only run. */
88 int file_err
, errs
= -1;
91 magic
= (struct magic
*) calloc(sizeof(struct magic
), maxmagic
);
92 mfn
= malloc(strlen(fn
)+1);
93 if (magic
== NULL
|| mfn
== NULL
) {
94 (void) fprintf(stderr
, "%s: Out of memory.\n", progname
);
100 fn
= strcpy(mfn
, fn
);
106 file_err
= apprentice_1(fn
, check
);
112 (void) fprintf(stderr
, "%s: couldn't find any magic files!\n",
122 apprentice_1(fn
, check
)
123 char *fn
; /* name of magic file */
124 int check
; /* non-zero? checking-only run. */
126 static const char hdr
[] =
127 "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
135 (void) fprintf(stderr
,
136 "%s: can't read magic file %s (%s)\n",
137 progname
, fn
, strerror(errno
));
142 if (check
) /* print silly verbose header for USG compat. */
143 (void) printf("%s\n", hdr
);
145 for (lineno
= 1;fgets(line
, BUFSIZ
, f
) != NULL
; lineno
++) {
146 if (line
[0]=='#') /* comment, do not parse */
148 if (strlen(line
) <= (unsigned)1) /* null line, garbage, etc */
150 line
[strlen(line
)-1] = '\0'; /* delete newline */
151 if (parse(line
, &nmagic
, check
) != 0)
160 * extend the sign bit if the comparison is to be signed
167 if (!(m
->flag
& UNSIGNED
))
170 * Do not remove the casts below. They are
171 * vital. When later compared with the data,
172 * the sign extension must have happened.
193 magwarn("can't happen: m->type=%d\n",
201 * parse one line from magic file, put into magic[index++] if valid
208 int i
= 0, nd
= *ndx
;
212 #define ALLOC_INCR 20
213 if (nd
+1 >= maxmagic
){
214 maxmagic
+= ALLOC_INCR
;
215 if ((magic
= (struct magic
*) realloc(magic
,
216 sizeof(struct magic
) *
217 maxmagic
)) == NULL
) {
218 (void) fprintf(stderr
, "%s: Out of memory.\n", progname
);
224 memset(&magic
[*ndx
], 0, sizeof(struct magic
) * ALLOC_INCR
);
235 if (m
->cont_level
!= 0 && *l
== '(') {
239 if (m
->cont_level
!= 0 && *l
== '&') {
244 /* get offset, then skip over it */
245 m
->offset
= (int) strtoul(l
,&t
,0);
247 magwarn("offset %s invalid", l
);
250 if (m
->flag
& INDIR
) {
254 * read [.lbs][+-]nnnnn)
258 switch (LOWCASE(*l
)) {
271 magwarn("indirect offset type %c invalid", *l
);
277 if (*l
== '+' || *l
== '-') l
++;
278 if (isdigit((unsigned char)*l
)) {
279 m
->in
.offset
= strtoul(l
, &t
, 0);
280 if (*s
== '-') m
->in
.offset
= - m
->in
.offset
;
285 magwarn("missing ')' in indirect offset");
290 while (isascii((unsigned char)*l
) && isdigit((unsigned char)*l
))
311 /* get type, skip it */
312 if (strncmp(l
, "byte", NBYTE
)==0) {
315 } else if (strncmp(l
, "short", NSHORT
)==0) {
318 } else if (strncmp(l
, "long", NLONG
)==0) {
321 } else if (strncmp(l
, "string", NSTRING
)==0) {
324 } else if (strncmp(l
, "date", NDATE
)==0) {
327 } else if (strncmp(l
, "beshort", NBESHORT
)==0) {
330 } else if (strncmp(l
, "belong", NBELONG
)==0) {
333 } else if (strncmp(l
, "bedate", NBEDATE
)==0) {
336 } else if (strncmp(l
, "leshort", NLESHORT
)==0) {
339 } else if (strncmp(l
, "lelong", NLELONG
)==0) {
342 } else if (strncmp(l
, "ledate", NLEDATE
)==0) {
346 magwarn("type %s invalid", l
);
349 /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
352 m
->mask
= signextend(m
, strtoul(l
, &l
, 0));
361 /* Old-style anding: "0 byte &0x80 dynamically linked" */
369 if (m
->type
!= STRING
) {
376 if (*l
== 'x' && isascii((unsigned char)l
[1]) &&
377 isspace((unsigned char)l
[1])) {
380 goto GetDesc
; /* Bill The Cat */
390 * TODO finish this macro and start using it!
391 * #define offsetcheck {if (offset > HOWMANY-1)
392 * magwarn("offset too big"); }
396 * now get last part - the description
403 } else if ((l
[0] == '\\') && (l
[1] == 'b')) {
409 while ((m
->desc
[i
++] = *l
++) != '\0' && i
<MAXDESC
)
415 ++(*ndx
); /* make room for next */
420 * Read a numeric value from a pointer, into the value union of a magic
421 * pointer, according to the magic type. Update the string pointer to point
422 * just after the number read. Return 0 for success, non-zero for failure.
431 if (m
->type
== STRING
) {
432 *p
= getstr(*p
, m
->value
.s
, sizeof(m
->value
.s
), &slen
);
435 if (m
->reln
!= 'x') {
436 m
->value
.l
= signextend(m
, strtoul(*p
, p
, 0));
443 * Convert a string containing C character escapes. Stop at an unescaped
445 * Copy the converted version to "p", returning its length in *slen.
446 * Return updated scan pointer as function result.
449 getstr(s
, p
, plen
, slen
)
454 char *origs
= s
, *origp
= p
;
455 char *pmax
= p
+ plen
- 1;
459 while ((c
= *s
++) != '\0') {
460 if (isspace((unsigned char) c
))
463 fprintf(stderr
, "String too long: %s\n", origs
);
500 /* \ and up to 3 octal digits */
510 c
= *s
++; /* try for 2 */
511 if(c
>= '0' && c
<= '7') {
512 val
= (val
<<3) | (c
- '0');
513 c
= *s
++; /* try for 3 */
514 if(c
>= '0' && c
<= '7')
515 val
= (val
<<3) | (c
-'0');
524 /* \x and up to 2 hex digits */
526 val
= 'x'; /* Default if no digits */
527 c
= hextoint(*s
++); /* Get next char */
532 val
= (val
<< 4) + c
;
550 /* Single hex char to int; -1 if not a hex char. */
555 if (!isascii((unsigned char) c
)) return -1;
556 if (isdigit((unsigned char) c
)) return c
- '0';
557 if ((c
>='a')&&(c
<='f')) return c
+ 10 - 'a';
558 if ((c
>='A')&&(c
<='F')) return c
+ 10 - 'A';
564 * Print a string containing C character escapes.
584 if(c
>= 040 && c
<= 0176) /* TODO isprint && !iscntrl */
587 (void) fputc('\\', fp
);
591 (void) fputc('n', fp
);
595 (void) fputc('r', fp
);
599 (void) fputc('b', fp
);
603 (void) fputc('t', fp
);
607 (void) fputc('f', fp
);
611 (void) fputc('v', fp
);
615 (void) fprintf(fp
, "%.3o", c
& 0377);
623 * eatsize(): Eat the size spec from a number [eg. 10UL]
631 if (LOWCASE(*l
) == 'u')
634 switch (LOWCASE(*l
)) {
636 case 's': /* short */
637 case 'h': /* short */
638 case 'b': /* char/byte */
639 case 'c': /* char/byte */