summaryrefslogtreecommitdiffstats
path: root/usr.bin/file/apprentice.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/file/apprentice.c')
-rw-r--r--usr.bin/file/apprentice.c621
1 files changed, 0 insertions, 621 deletions
diff --git a/usr.bin/file/apprentice.c b/usr.bin/file/apprentice.c
deleted file mode 100644
index 7d8d9e2..0000000
--- a/usr.bin/file/apprentice.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include "file.h"
-
-#ifndef lint
-static char *moduleid =
- "@(#)$Id: apprentice.c,v 1.25 1997/01/15 17:23:24 christos Exp $";
-#endif /* lint */
-
-#define EATAB {while (isascii((unsigned char) *l) && \
- isspace((unsigned char) *l)) ++l;}
-#define LOWCASE(l) (isupper((unsigned char) (l)) ? \
- tolower((unsigned char) (l)) : (l))
-
-
-static int getvalue __P((struct magic *, char **));
-static int hextoint __P((int));
-static char *getstr __P((char *, char *, int, int *));
-static int parse __P((char *, int *, int));
-static void eatsize __P((char **));
-
-static int maxmagic = 0;
-
-static int apprentice_1 __P((char *, int));
-
-int
-apprentice(fn, check)
-char *fn; /* list of magic files */
-int check; /* non-zero? checking-only run. */
-{
- char *p, *mfn;
- int file_err, errs = -1;
-
- maxmagic = MAXMAGIS;
- magic = (struct magic *) calloc(sizeof(struct magic), maxmagic);
- mfn = malloc(strlen(fn)+1);
- if (magic == NULL || mfn == NULL) {
- (void) fprintf(stderr, "%s: Out of memory.\n", progname);
- if (check)
- return -1;
- else
- exit(1);
- }
- fn = strcpy(mfn, fn);
-
- while (fn) {
- p = strchr(fn, ':');
- if (p)
- *p++ = '\0';
- file_err = apprentice_1(fn, check);
- if (file_err > errs)
- errs = file_err;
- fn = p;
- }
- if (errs == -1)
- (void) fprintf(stderr, "%s: couldn't find any magic files!\n",
- progname);
- if (!check && errs)
- exit(1);
-
- free(mfn);
- return errs;
-}
-
-static int
-apprentice_1(fn, check)
-char *fn; /* name of magic file */
-int check; /* non-zero? checking-only run. */
-{
- static const char hdr[] =
- "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
- FILE *f;
- char line[BUFSIZ+1];
- int errs = 0;
-
- f = fopen(fn, "r");
- if (f==NULL) {
- if (errno != ENOENT)
- (void) fprintf(stderr,
- "%s: can't read magic file %s (%s)\n",
- progname, fn, strerror(errno));
- return -1;
- }
-
- /* parse it */
- if (check) /* print silly verbose header for USG compat. */
- (void) printf("%s\n", hdr);
-
- for (lineno = 1;fgets(line, BUFSIZ, f) != NULL; lineno++) {
- if (line[0]=='#') /* comment, do not parse */
- continue;
- if (strlen(line) <= (unsigned)1) /* null line, garbage, etc */
- continue;
- line[strlen(line)-1] = '\0'; /* delete newline */
- if (parse(line, &nmagic, check) != 0)
- errs = 1;
- }
-
- (void) fclose(f);
- return errs;
-}
-
-/*
- * extend the sign bit if the comparison is to be signed
- */
-uint32
-signextend(m, v)
-struct magic *m;
-uint32 v;
-{
- if (!(m->flag & UNSIGNED))
- switch(m->type) {
- /*
- * Do not remove the casts below. They are
- * vital. When later compared with the data,
- * the sign extension must have happened.
- */
- case BYTE:
- v = (char) v;
- break;
- case SHORT:
- case BESHORT:
- case LESHORT:
- v = (short) v;
- break;
- case DATE:
- case BEDATE:
- case LEDATE:
- case LONG:
- case BELONG:
- case LELONG:
- v = (int32) v;
- break;
- case STRING:
- break;
- default:
- magwarn("can't happen: m->type=%d\n",
- m->type);
- return -1;
- }
- return v;
-}
-
-/*
- * parse one line from magic file, put into magic[index++] if valid
- */
-static int
-parse(l, ndx, check)
-char *l;
-int *ndx, check;
-{
- int i = 0, nd = *ndx;
- struct magic *m;
- char *t, *s;
-
-#define ALLOC_INCR 20
- if (nd+1 >= maxmagic){
- maxmagic += ALLOC_INCR;
- if ((magic = (struct magic *) realloc(magic,
- sizeof(struct magic) *
- maxmagic)) == NULL) {
- (void) fprintf(stderr, "%s: Out of memory.\n", progname);
- if (check)
- return -1;
- else
- exit(1);
- }
- memset(&magic[*ndx], 0, sizeof(struct magic) * ALLOC_INCR);
- }
- m = &magic[*ndx];
- m->flag = 0;
- m->cont_level = 0;
-
- while (*l == '>') {
- ++l; /* step over */
- m->cont_level++;
- }
-
- if (m->cont_level != 0 && *l == '(') {
- ++l; /* step over */
- m->flag |= INDIR;
- }
- if (m->cont_level != 0 && *l == '&') {
- ++l; /* step over */
- m->flag |= ADD;
- }
-
- /* get offset, then skip over it */
- m->offset = (int) strtoul(l,&t,0);
- if (l == t)
- magwarn("offset %s invalid", l);
- l = t;
-
- if (m->flag & INDIR) {
- m->in.type = LONG;
- m->in.offset = 0;
- /*
- * read [.lbs][+-]nnnnn)
- */
- if (*l == '.') {
- l++;
- switch (LOWCASE(*l)) {
- case 'l':
- m->in.type = LONG;
- break;
- case 'h':
- case 's':
- m->in.type = SHORT;
- break;
- case 'c':
- case 'b':
- m->in.type = BYTE;
- break;
- default:
- magwarn("indirect offset type %c invalid", *l);
- break;
- }
- l++;
- }
- s = l;
- if (*l == '+' || *l == '-') l++;
- if (isdigit((unsigned char)*l)) {
- m->in.offset = strtoul(l, &t, 0);
- if (*s == '-') m->in.offset = - m->in.offset;
- }
- else
- t = l;
- if (*t++ != ')')
- magwarn("missing ')' in indirect offset");
- l = t;
- }
-
-
- while (isascii((unsigned char)*l) && isdigit((unsigned char)*l))
- ++l;
- EATAB;
-
-#define NBYTE 4
-#define NSHORT 5
-#define NLONG 4
-#define NSTRING 6
-#define NDATE 4
-#define NBESHORT 7
-#define NBELONG 6
-#define NBEDATE 6
-#define NLESHORT 7
-#define NLELONG 6
-#define NLEDATE 6
-
- if (*l == 'u') {
- ++l;
- m->flag |= UNSIGNED;
- }
-
- /* get type, skip it */
- if (strncmp(l, "byte", NBYTE)==0) {
- m->type = BYTE;
- l += NBYTE;
- } else if (strncmp(l, "short", NSHORT)==0) {
- m->type = SHORT;
- l += NSHORT;
- } else if (strncmp(l, "long", NLONG)==0) {
- m->type = LONG;
- l += NLONG;
- } else if (strncmp(l, "string", NSTRING)==0) {
- m->type = STRING;
- l += NSTRING;
- } else if (strncmp(l, "date", NDATE)==0) {
- m->type = DATE;
- l += NDATE;
- } else if (strncmp(l, "beshort", NBESHORT)==0) {
- m->type = BESHORT;
- l += NBESHORT;
- } else if (strncmp(l, "belong", NBELONG)==0) {
- m->type = BELONG;
- l += NBELONG;
- } else if (strncmp(l, "bedate", NBEDATE)==0) {
- m->type = BEDATE;
- l += NBEDATE;
- } else if (strncmp(l, "leshort", NLESHORT)==0) {
- m->type = LESHORT;
- l += NLESHORT;
- } else if (strncmp(l, "lelong", NLELONG)==0) {
- m->type = LELONG;
- l += NLELONG;
- } else if (strncmp(l, "ledate", NLEDATE)==0) {
- m->type = LEDATE;
- l += NLEDATE;
- } else {
- magwarn("type %s invalid", l);
- return -1;
- }
- /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
- if (*l == '&') {
- ++l;
- m->mask = signextend(m, strtoul(l, &l, 0));
- eatsize(&l);
- } else
- m->mask = ~0L;
- EATAB;
-
- switch (*l) {
- case '>':
- case '<':
- /* Old-style anding: "0 byte &0x80 dynamically linked" */
- case '&':
- case '^':
- case '=':
- m->reln = *l;
- ++l;
- break;
- case '!':
- if (m->type != STRING) {
- m->reln = *l;
- ++l;
- break;
- }
- /* FALL THROUGH */
- default:
- if (*l == 'x' && isascii((unsigned char)l[1]) &&
- isspace((unsigned char)l[1])) {
- m->reln = *l;
- ++l;
- goto GetDesc; /* Bill The Cat */
- }
- m->reln = '=';
- break;
- }
- EATAB;
-
- if (getvalue(m, &l))
- return -1;
- /*
- * TODO finish this macro and start using it!
- * #define offsetcheck {if (offset > HOWMANY-1)
- * magwarn("offset too big"); }
- */
-
- /*
- * now get last part - the description
- */
-GetDesc:
- EATAB;
- if (l[0] == '\b') {
- ++l;
- m->nospflag = 1;
- } else if ((l[0] == '\\') && (l[1] == 'b')) {
- ++l;
- ++l;
- m->nospflag = 1;
- } else
- m->nospflag = 0;
- while ((m->desc[i++] = *l++) != '\0' && i<MAXDESC)
- /* NULLBODY */;
-
- if (check) {
- mdump(m);
- }
- ++(*ndx); /* make room for next */
- return 0;
-}
-
-/*
- * Read a numeric value from a pointer, into the value union of a magic
- * pointer, according to the magic type. Update the string pointer to point
- * just after the number read. Return 0 for success, non-zero for failure.
- */
-static int
-getvalue(m, p)
-struct magic *m;
-char **p;
-{
- int slen;
-
- if (m->type == STRING) {
- *p = getstr(*p, m->value.s, sizeof(m->value.s), &slen);
- m->vallen = slen;
- } else
- if (m->reln != 'x') {
- m->value.l = signextend(m, strtoul(*p, p, 0));
- eatsize(p);
- }
- return 0;
-}
-
-/*
- * Convert a string containing C character escapes. Stop at an unescaped
- * space or tab.
- * Copy the converted version to "p", returning its length in *slen.
- * Return updated scan pointer as function result.
- */
-static char *
-getstr(s, p, plen, slen)
-register char *s;
-register char *p;
-int plen, *slen;
-{
- char *origs = s, *origp = p;
- char *pmax = p + plen - 1;
- register int c;
- register int val;
-
- while ((c = *s++) != '\0') {
- if (isspace((unsigned char) c))
- break;
- if (p >= pmax) {
- fprintf(stderr, "String too long: %s\n", origs);
- break;
- }
- if(c == '\\') {
- switch(c = *s++) {
-
- case '\0':
- goto out;
-
- default:
- *p++ = (char) c;
- break;
-
- case 'n':
- *p++ = '\n';
- break;
-
- case 'r':
- *p++ = '\r';
- break;
-
- case 'b':
- *p++ = '\b';
- break;
-
- case 't':
- *p++ = '\t';
- break;
-
- case 'f':
- *p++ = '\f';
- break;
-
- case 'v':
- *p++ = '\v';
- break;
-
- /* \ and up to 3 octal digits */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- val = c - '0';
- c = *s++; /* try for 2 */
- if(c >= '0' && c <= '7') {
- val = (val<<3) | (c - '0');
- c = *s++; /* try for 3 */
- if(c >= '0' && c <= '7')
- val = (val<<3) | (c-'0');
- else
- --s;
- }
- else
- --s;
- *p++ = (char)val;
- break;
-
- /* \x and up to 2 hex digits */
- case 'x':
- val = 'x'; /* Default if no digits */
- c = hextoint(*s++); /* Get next char */
- if (c >= 0) {
- val = c;
- c = hextoint(*s++);
- if (c >= 0)
- val = (val << 4) + c;
- else
- --s;
- } else
- --s;
- *p++ = (char)val;
- break;
- }
- } else
- *p++ = (char)c;
- }
-out:
- *p = '\0';
- *slen = p - origp;
- return s;
-}
-
-
-/* Single hex char to int; -1 if not a hex char. */
-static int
-hextoint(c)
-int c;
-{
- if (!isascii((unsigned char) c)) return -1;
- if (isdigit((unsigned char) c)) return c - '0';
- if ((c>='a')&&(c<='f')) return c + 10 - 'a';
- if ((c>='A')&&(c<='F')) return c + 10 - 'A';
- return -1;
-}
-
-
-/*
- * Print a string containing C character escapes.
- */
-void
-showstr(fp, s, len)
-FILE *fp;
-const char *s;
-int len;
-{
- register char c;
-
- for (;;) {
- c = *s++;
- if (len == -1) {
- if (c == '\0')
- break;
- }
- else {
- if (len-- == 0)
- break;
- }
- if(c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */
- (void) fputc(c, fp);
- else {
- (void) fputc('\\', fp);
- switch (c) {
-
- case '\n':
- (void) fputc('n', fp);
- break;
-
- case '\r':
- (void) fputc('r', fp);
- break;
-
- case '\b':
- (void) fputc('b', fp);
- break;
-
- case '\t':
- (void) fputc('t', fp);
- break;
-
- case '\f':
- (void) fputc('f', fp);
- break;
-
- case '\v':
- (void) fputc('v', fp);
- break;
-
- default:
- (void) fprintf(fp, "%.3o", c & 0377);
- break;
- }
- }
- }
-}
-
-/*
- * eatsize(): Eat the size spec from a number [eg. 10UL]
- */
-static void
-eatsize(p)
-char **p;
-{
- char *l = *p;
-
- if (LOWCASE(*l) == 'u')
- l++;
-
- switch (LOWCASE(*l)) {
- case 'l': /* long */
- case 's': /* short */
- case 'h': /* short */
- case 'b': /* char/byte */
- case 'c': /* char/byte */
- l++;
- /*FALLTHROUGH*/
- default:
- break;
- }
-
- *p = l;
-}
OpenPOWER on IntegriCloud