Module Name:    src
Committed By:   tsutsui
Date:           Fri May 31 19:52:25 UTC 2024

Added Files:
        src/external/gpl2/mkhybrid/dist/libfile: LEGAL.NOTICE README
            apprentice.c file.h lfile.c patchlevel.h softmagic.c

Log Message:
Import BSD licensed libfile for mkhybrid builds from cdrtools-3.01.

- unnecessary files for tools build are not imported
- file.c is renamed to lfile.c to avoid conflict with libhfs_iso
- RCSId strings are trimmed


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/external/gpl2/mkhybrid/dist/libfile/LEGAL.NOTICE \
    src/external/gpl2/mkhybrid/dist/libfile/README \
    src/external/gpl2/mkhybrid/dist/libfile/apprentice.c \
    src/external/gpl2/mkhybrid/dist/libfile/file.h \
    src/external/gpl2/mkhybrid/dist/libfile/lfile.c \
    src/external/gpl2/mkhybrid/dist/libfile/patchlevel.h \
    src/external/gpl2/mkhybrid/dist/libfile/softmagic.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/external/gpl2/mkhybrid/dist/libfile/LEGAL.NOTICE
diff -u /dev/null src/external/gpl2/mkhybrid/dist/libfile/LEGAL.NOTICE:1.1
--- /dev/null	Fri May 31 19:52:25 2024
+++ src/external/gpl2/mkhybrid/dist/libfile/LEGAL.NOTICE	Fri May 31 19:52:25 2024
@@ -0,0 +1,37 @@
+# @(#)LEGAL.NOTICE	1.2 08/10/19 joerg
+Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995.
+Software written by Ian F. Darwin and others; maintained by Christos Zoulas.
+Id: LEGAL.NOTICE,v 1.9 1995/10/27 23:14:20 christos Exp
+
+License changed Oct 19th 2008 by J. Schilling with permission from
+Ian F. Darwin, Christos Zoulas and James Pearson to:
+
+File: COPYING,v 1.1 2008/02/05 19:08:11 christos Exp
+Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995.
+Software written by Ian F. Darwin and others;
+maintained 1994- Christos Zoulas.
+
+This software is not subject to any export provision of the United States
+Department of Commerce, and may be exported to any country or planet.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice immediately at the beginning of the file, without modification,
+   this list of conditions, and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+ 
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
Index: src/external/gpl2/mkhybrid/dist/libfile/README
diff -u /dev/null src/external/gpl2/mkhybrid/dist/libfile/README:1.1
--- /dev/null	Fri May 31 19:52:25 2024
+++ src/external/gpl2/mkhybrid/dist/libfile/README	Fri May 31 19:52:25 2024
@@ -0,0 +1,70 @@
+# @(#)README	1.1 98/06/16 joerg
+
+Find file types by using a modified "magic" file
+
+Based on file v3.22 by Ian F. Darwin (see libfile/LEGAL.NOTICE and
+libfile/README.dist - File v3.22 can be found at many archive sites)
+
+For each entry in the magic file, the "message" for the initial offset MUST
+be 4 characters for the CREATOR and 4 characters for the TYPE - white space is
+optional between them. Any other characters on this line are ignored.
+Continuation lines (starting with a '>') are also ignored i.e. only the initial
+offset lines are used.
+
+e.g magic entry for a GIF file:
+
+# off	type		test		message
+#
+# GIF image
+0       string          GIF8            8BIM GIFf
+>4      string          7a              \b, version 8%s,
+>4      string          9a              \b, version 8%s,
+>6      leshort         >0              %hd x
+>8      leshort         >0              %hd,
+#>10    byte            &0x80           color mapped,
+#>10    byte&0x07       =0x00           2 colors
+#>10    byte&0x07       =0x01           4 colors
+#>10    byte&0x07       =0x02           8 colors
+#>10    byte&0x07       =0x03           16 colors
+#>10    byte&0x07       =0x04           32 colors
+#>10    byte&0x07       =0x05           64 colors
+#>10    byte&0x07       =0x06           128 colors
+#>10    byte&0x07       =0x07           256 colors
+
+Just the "8BIM" "GIFf" will be used whatever the type of GIF file it is.
+The continuation lines are used by the "file" command, but ignored by
+mkhybrid. They could be left out completely.
+
+The complete format of the magic file is given in the magic man page (magic.5).
+
+See the file "magic" for other examples
+
+Use with the -magic magic_file option, where magic_file is a file
+described above.
+
+The magic file can be used with the mapping file (option -map) - the order
+these options appear on the command line is important.  mkhybrid will try to
+detect if the file is one of the Unix/Mac files (e.g. a CAP or Netatalk
+file) first. If that fails, it will then use the magic and/or mapping
+file e.g:
+
+mkhybrid -o output.raw -map mapping -magic magic src_dir
+
+The above will check filename extensions first, if that fails to set the
+CREATOR/TYPE, the magic file will be used. To check the magic file
+before the filename extensions, use:
+
+mkhybrid -o output.raw -magic magic -map mapping src_dir
+
+
+Using just a magic file - filename extensions will not be checked e.g:
+
+mkhybrid -o output.raw -magic magic src_dir
+
+For the magic method to work, each file must be opened and read twice
+(once to find it's CREATOR/TYPE, and a second time to actually copy the
+file to the CD image). Therefore the -magic option may significantly
+increase processing time.
+
+If a file's CREATOR/TYPE is not set via the magic and mapping matches,
+then the file is given the default CREATOR/TYPE.
Index: src/external/gpl2/mkhybrid/dist/libfile/apprentice.c
diff -u /dev/null src/external/gpl2/mkhybrid/dist/libfile/apprentice.c:1.1
--- /dev/null	Fri May 31 19:52:25 2024
+++ src/external/gpl2/mkhybrid/dist/libfile/apprentice.c	Fri May 31 19:52:25 2024
@@ -0,0 +1,627 @@
+/* @(#)apprentice.c	1.13 09/07/11 joerg */
+#include <schily/mconfig.h>
+#ifndef lint
+static	UConst char sccsid[] =
+	"@(#)apprentice.c	1.13 09/07/11 joerg";
+#endif
+/*
+**	find file types by using a modified "magic" file
+**
+**	based on file v3.22 by Ian F. Darwin (see below)
+**
+**	Modified for mkhybrid James Pearson 19/5/98
+*/
+
+/*
+ * 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 export provision of the United States
+ * Department of Commerce, and may be exported to any country or planet.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice immediately at the beginning of the file, without modification,
+ *    this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <schily/stdio.h>
+#include <schily/stdlib.h>
+#include <schily/string.h>
+#include <schily/ctype.h>
+#include "file.h"
+#include <schily/schily.h>
+
+#ifndef	lint
+static UConst char moduleid[] = 
+	"@(#)Id: apprentice.c,v 1.25 1997/01/15 17:23:24 christos Exp";
+#endif	/* lint */
+
+int	__f_nmagic = 0;		/* number of valid magic[]s 		*/
+#if	defined(IS_MACOS_X)
+/*
+ * The MAC OS X linker does not grok "common" varaibles.
+ * Make __f_magic a "data" variable.
+ */
+struct  magic *__f_magic = 0;	/* array of magic entries		*/
+#else
+struct  magic *__f_magic;	/* array of magic entries		*/
+#endif
+
+#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	__PR((struct magic *, char **));
+static int hextoint	__PR((int));
+static char *apgetstr	__PR((char *, char *, int, int *));
+static int parse	__PR((char *, int *, int));
+static void eatsize	__PR((char **));
+
+static int maxmagic = 0;
+
+static int apprentice_1	__PR((char *, int));
+
+/*
+ * init_magic - read magic file and set up mapping
+ * based on the original apprentice()
+ */
+int
+init_magic(fn)
+char *fn;			/* list of magic files */
+{
+        maxmagic = MAXMAGIS;
+	__f_magic = (struct magic *) calloc(sizeof(struct magic), maxmagic);
+	if (__f_magic == NULL) 
+		return -1;
+
+	return(apprentice_1(fn, 0));
+}
+
+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;
+	int lineno;
+
+	f = fopen(fn, "r");
+	if (f==NULL) {
+		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, &__f_nmagic, check) != 0)
+			errs = 1;
+	}
+
+	(void) fclose(f);
+	return errs;
+}
+
+/*
+ * extend the sign bit if the comparison is to be signed
+ * XXX is uint32 really a good idea XXX JS
+ */
+UInt32_t
+signextend(m, v)
+struct magic *m;
+UInt32_t 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_t) v;
+			break;
+		case STRING:
+			break;
+		default:
+			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 ((__f_magic = (struct magic *) realloc(__f_magic, 
+						  sizeof(struct magic) * 
+						  maxmagic)) == NULL) {
+#ifdef	MAIN
+		(void) fprintf(stderr, "%s: Out of memory.\n", progname);
+#else
+		(void) fprintf(stderr, "libfile: Out of memory.\n");
+#endif
+		if (check)
+			return -1;
+		else
+			exit(1);
+	    }
+	    memset(&__f_magic[*ndx], 0, sizeof(struct magic) * ALLOC_INCR);
+	}
+	m = &__f_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:
+				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 {
+		return -1;
+	}
+	/* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
+	if (*l == '&') {
+		++l;
+		m->mask = signextend(m, (UInt32_t)strtoul(l, &l, 0)); /* XXX JS uint32 cat may be wrong */
+		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 */;
+
+	++(*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 = apgetstr(*p, m->value.s, sizeof(m->value.s), &slen);
+		m->vallen = slen;
+	} else
+		if (m->reln != 'x') {
+			m->value.l = signextend(m, (UInt32_t)strtoul(*p, p, 0)); /* XXX JS uint32 cat may be wrong */
+			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 *
+apgetstr(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;
+}
Index: src/external/gpl2/mkhybrid/dist/libfile/file.h
diff -u /dev/null src/external/gpl2/mkhybrid/dist/libfile/file.h:1.1
--- /dev/null	Fri May 31 19:52:25 2024
+++ src/external/gpl2/mkhybrid/dist/libfile/file.h	Fri May 31 19:52:25 2024
@@ -0,0 +1,143 @@
+/* @(#)file.h	1.12 09/07/13 joerg */
+/*
+ * file.h - definitions for file(1) program
+ * @(#)Id: file.h,v 1.25 1997/01/15 19:28:35 christos Exp
+ *
+ * Copyright (c) Ian F. Darwin, 1987.
+ * Written by Ian F. Darwin.
+ *
+ * This software is not subject to any export provision of the United States
+ * Department of Commerce, and may be exported to any country or planet.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice immediately at the beginning of the file, without modification,
+ *    this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __file_h__
+#define __file_h__
+
+#ifndef	_SCHILY_MCONFIG_H
+#include <schily/mconfig.h>
+#endif
+#include <schily/utypes.h>
+
+#ifndef HOWMANY
+# define HOWMANY 8192		/* how much of the file to look at */
+#endif
+#define MAXMAGIS 1000		/* max entries in /etc/magic */
+#define MAXDESC	50		/* max leng of text description */
+#define MAXstring 32		/* max leng of "string" types */
+
+struct magic {
+	short flag;		
+#define INDIR	1		/* if '>(...)' appears,  */
+#define	UNSIGNED 2		/* comparison is unsigned */
+#define ADD	4		/* if '>&' appears,  */
+	short cont_level;	/* level of ">" */
+	struct {
+		char type;	/* byte short long */
+		Int32_t offset;	/* offset from indirection */
+	} in;
+	Int32_t offset;		/* offset to magic number */
+	unsigned char reln;	/* relation (0=eq, '>'=gt, etc) */
+	char type;		/* int, short, long or string. */
+	char vallen;		/* length of string value, if any */
+#define 			BYTE	1
+#define				SHORT	2
+#define				LONG	4
+#define				STRING	5
+#define				DATE	6
+#define				BESHORT	7
+#define				BELONG	8
+#define				BEDATE	9
+#define				LESHORT	10
+#define				LELONG	11
+#define				LEDATE	12
+	union VALUETYPE {
+		unsigned char b;
+		unsigned short h;
+		UInt32_t l;
+		char s[MAXstring];
+		unsigned char hs[2];	/* 2 bytes of a fixed-endian "short" */
+		unsigned char hl[4];	/* 2 bytes of a fixed-endian "long" */
+	} value;		/* either number or string */
+	UInt32_t mask;	/* mask before comparison with value */
+	char nospflag;		/* supress space character */
+	char desc[MAXDESC];	/* description */
+};
+
+#include <schily/stdio.h>
+
+extern int   init_magic		__PR((char *));
+extern int   ascmagic		__PR((unsigned char *, int));
+/*extern void  error		__PR((const char *, ...));*/
+extern void  ckfputs		__PR((const char *, FILE *));
+struct stat;
+extern int   fsmagic		__PR((const char *, struct stat *));
+extern int   is_compress	__PR((const unsigned char *, int *));
+extern int   is_tar		__PR((unsigned char *, int));
+extern void  magwarn		__PR((const char *, ...));
+extern void  mdump		__PR((struct magic *));
+extern char *get_magic_magic	__PR((const char *));
+extern void  showstr		__PR((FILE *, const char *, int));
+extern char *softmagic		__PR((unsigned char *, int));
+extern int   tryit		__PR((unsigned char *, int, int));
+extern int   zmagic		__PR((unsigned char *, int));
+extern void  ckfprintf		__PR((FILE *, const char *, ...));
+#ifndef __BEOS__
+extern UInt32_t signextend	__PR((struct magic *, UInt32_t));
+#endif /* __BEOS__ */
+extern int internatmagic	__PR((unsigned char *, int));
+extern void tryelf		__PR((int, char *, int));
+
+
+extern char *progname;		/* the program name 			*/
+extern char *magicfile;		/* name of the magic file		*/
+
+extern struct magic *__f_magic;	/* array of magic entries		*/
+extern int __f_nmagic;		/* number of valid magic[]s 		*/
+
+
+extern int debug;		/* enable debugging?			*/
+extern int zflag;		/* process compressed files?		*/
+extern int lflag;		/* follow symbolic links?		*/
+
+#if defined(sun) || defined(__sun__) || defined (__sun)
+# if defined(__svr4) || defined (__SVR4) || defined(__svr4__)
+#  define SOLARIS
+# else
+#  define SUNOS
+# endif
+#endif
+
+
+#ifndef	HAVE_STRERROR
+extern int sys_nerr;
+extern char *sys_errlist[];
+#define strerror(e) \
+	(((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error")
+#endif
+#ifndef	HAVE_STRTOUL
+#define strtoul(a, b, c)	strtol(a, b, c)
+#endif
+
+#endif /* __file_h__ */
Index: src/external/gpl2/mkhybrid/dist/libfile/lfile.c
diff -u /dev/null src/external/gpl2/mkhybrid/dist/libfile/lfile.c:1.1
--- /dev/null	Fri May 31 19:52:25 2024
+++ src/external/gpl2/mkhybrid/dist/libfile/lfile.c	Fri May 31 19:52:25 2024
@@ -0,0 +1,286 @@
+/* @(#)file.c	1.10 09/08/04 joerg */
+#include <schily/mconfig.h>
+#ifndef lint
+static	UConst char sccsid[] =
+	"@(#)file.c	1.10 09/08/04 joerg";
+#endif
+/*
+**	find file types by using a modified "magic" file
+**
+**	based on file v3.22 by Ian F. Darwin (see below)
+**
+**	For each entry in the magic file, the message MUST start with
+**	two 4 character strings which are the CREATOR and TYPE for the
+**	Mac file. Any continuation lines are ignored. e.g magic entry
+**	for a GIF file:
+**	
+**	0       string          GIF8            8BIM GIFf
+**	>4      string          7a              \b, version 8%s,
+**	>4      string          9a              \b, version 8%s,
+**	>6      leshort         >0              %hd x
+**	>8      leshort         >0              %hd,
+**	#>10    byte            &0x80           color mapped,
+**	#>10    byte&0x07       =0x00           2 colors
+**	#>10    byte&0x07       =0x01           4 colors
+**	#>10    byte&0x07       =0x02           8 colors
+**	#>10    byte&0x07       =0x03           16 colors
+**	#>10    byte&0x07       =0x04           32 colors
+**	#>10    byte&0x07       =0x05           64 colors
+**	#>10    byte&0x07       =0x06           128 colors
+**	#>10    byte&0x07       =0x07           256 colors
+**
+**	Just the "8BIM" "GIFf" will be used whatever the type GIF file
+**	it is.
+**
+**	Modified for mkhybrid James Pearson 19/5/98
+*/
+
+/*
+ * file - find type of a file or files - main program.
+ *
+ * Copyright (c) Ian F. Darwin, 1987.
+ * Written by Ian F. Darwin.
+ *
+ * This software is not subject to any export provision of the United States
+ * Department of Commerce, and may be exported to any country or planet.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice immediately at the beginning of the file, without modification,
+ *    this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef	lint
+static UConst char moduleid[] = 
+	"@(#)Id: file.c,v 1.38 1997/01/15 19:28:35 christos Exp";
+#endif	/* lint */
+
+#include <schily/stdio.h>
+#include <schily/stdlib.h>
+#include <schily/unistd.h>	/* for read() */
+#include <schily/stat.h>
+#include <schily/fcntl.h>	/* for open() */
+
+#ifdef RESTORE_TIME
+#include <schily/utime.h>
+#ifdef HAVE_UTIMES
+#define	USE_UTIMES
+#endif
+#endif
+
+#if 0
+#include <schily/in.h>		/* for byte swapping */
+#endif
+
+#include "patchlevel.h"
+#include "file.h"
+
+#ifdef MAIN
+ 			/* Global command-line options 		*/
+#ifdef DEBUG
+int	debug = 1; 	/* debugging 				*/
+#else
+int	debug = 0; 	/* debugging 				*/
+#endif /* DEBUG */
+int	lflag = 0;	/* follow Symlinks (BSD only) 		*/
+int	zflag = 0;	/* follow (uncompress) compressed files */
+
+			/* Misc globals				*/
+char *magicfile;	/* where magic be found 		*/
+
+char *progname;		/* used throughout 			*/
+#endif
+
+char *	get_magic_match	__PR((const char *inname));
+void	clean_magic	__PR((void));
+
+#if 0
+static int	byteconv4	__P((int, int, int));
+static short	byteconv2	__P((int, int, int));
+#endif
+
+#if 0
+/*
+ * byteconv4
+ * Input:
+ *	from		4 byte quantity to convert
+ *	same		whether to perform byte swapping
+ *	big_endian	whether we are a big endian host
+ */
+static int
+byteconv4(from, same, big_endian)
+    int from;
+    int same;
+    int big_endian;
+{
+  if (same)
+    return from;
+  else if (big_endian)		/* lsb -> msb conversion on msb */
+  {
+    union {
+      int i;
+      char c[4];
+    } retval, tmpval;
+
+    tmpval.i = from;
+    retval.c[0] = tmpval.c[3];
+    retval.c[1] = tmpval.c[2];
+    retval.c[2] = tmpval.c[1];
+    retval.c[3] = tmpval.c[0];
+
+    return retval.i;
+  }
+  else
+    return ntohl(from);		/* msb -> lsb conversion on lsb */
+}
+
+/*
+ * byteconv2
+ * Same as byteconv4, but for shorts
+ */
+static short
+byteconv2(from, same, big_endian)
+	int from;
+	int same;
+	int big_endian;
+{
+  if (same)
+    return from;
+  else if (big_endian)		/* lsb -> msb conversion on msb */
+  {
+    union {
+      short s;
+      char c[2];
+    } retval, tmpval;
+
+    tmpval.s = (short) from;
+    retval.c[0] = tmpval.c[1];
+    retval.c[1] = tmpval.c[0];
+
+    return retval.s;
+  }
+  else
+    return ntohs(from);		/* msb -> lsb conversion on lsb */
+}
+#endif
+
+/*
+ * get_magic_match - get the CREATOR/TYPE string
+ * based on the original process()
+ */
+char *
+get_magic_match(inname)
+const char	*inname;
+{
+	int	fd = 0;
+	unsigned char	buf[HOWMANY+1];	/* one extra for terminating '\0' */
+	struct stat	sb;
+	int nbytes = 0;	/* number of bytes read from a datafile */
+	char *match;
+
+	/* check the file is regular and non-zero length */
+	if (stat(inname, &sb) != 0)
+		return 0;
+
+	if (sb.st_size == 0 || ! S_ISREG(sb.st_mode))
+		return 0;
+
+	if ((fd = open(inname, O_RDONLY)) < 0)
+		    return 0;
+
+	/*
+	 * try looking at the first HOWMANY bytes
+	 */
+	if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1)
+		return 0;
+
+	if (nbytes == 0)
+		return 0;
+	else {
+		buf[nbytes++] = '\0';	/* null-terminate it */
+		match = softmagic(buf, nbytes);
+	}
+
+#ifdef RESTORE_TIME
+	/* really no point as we going to access the file later anyway */
+	{
+		/*
+		 * Try to restore access, modification times if read it.
+		 */
+# ifdef USE_UTIMES
+		struct timeval  utsbuf[2];
+		utsbuf[0].tv_sec = sb.st_atime;
+		utsbuf[1].tv_sec = sb.st_mtime;
+
+		(void) utimes(inname, utsbuf); /* don't care if loses */
+# else
+		struct utimbuf  utbuf;
+
+		utbuf.actime = sb.st_atime;
+		utbuf.modtime = sb.st_mtime;
+		(void) utime(inname, &utbuf); /* don't care if loses */
+# endif
+	}
+#endif
+	(void) close(fd);
+
+	return(match);
+}
+
+/*
+ * clean_magic - deallocate memory used
+ */
+void
+clean_magic()
+{
+	if (__f_magic)
+		free(__f_magic);
+}
+	
+
+#ifdef MAIN
+main(argc, argv)
+int	argc;
+char	**argv;
+{
+	char	*ret;
+	char	creator[5];
+	char	type[5];
+
+	if (argc < 3)
+		exit(1);
+
+	init_magic(argv[1]);
+
+	ret = get_magic_match(argv[2]);
+
+	if (!ret)
+		ret = "unixTEXT";
+
+	sscanf(ret, "%4s%4s", creator, type);
+
+	creator[4] = type[4] = '\0';
+
+	printf("%s %s\n", creator, type);
+
+
+	exit(0);
+}
+#endif /* MAIN */
+
Index: src/external/gpl2/mkhybrid/dist/libfile/patchlevel.h
diff -u /dev/null src/external/gpl2/mkhybrid/dist/libfile/patchlevel.h:1.1
--- /dev/null	Fri May 31 19:52:25 2024
+++ src/external/gpl2/mkhybrid/dist/libfile/patchlevel.h	Fri May 31 19:52:25 2024
@@ -0,0 +1,108 @@
+/* @(#)patchlevel.h	1.1 97/01/15 joerg */
+#define	FILE_VERSION_MAJOR	3
+#define	patchlevel		22
+
+/*
+ * Patchlevel file for Ian Darwin's MAGIC command.
+ * Id: patchlevel.h,v 1.22 1997/01/15 17:23:24 christos Exp
+ *
+ * Log: patchlevel.h,v
+ * Revision 1.22  1997/01/15 17:23:24  christos
+ * - add support for elf core files: find the program name under SVR4 [Ken Pizzini]
+ * - print strings only up to the first carriage return [various]
+ * - freebsd international ascii support [J Wunsch]
+ * - magic fixes and additions [Guy Harris]
+ * - 64 bit fixes [Larry Schwimmer]
+ * - support for both utime and utimes, but don't restore file access times
+ *   by default [various]
+ * - \xXX only takes 2 hex digits, not 3.
+ * - re-implement support for core files [Guy Harris]
+ *
+ * Revision 1.21  1996/10/05 18:15:29  christos
+ * Segregate elf stuff and conditionally enable it with -DBUILTIN_ELF
+ * More magic fixes
+ *
+ * Revision 1.20  1996/06/22  22:15:52  christos
+ * - support relative offsets of the form >&
+ * - fix bug with truncating magic strings that contain \n
+ * - file -f - did not read from stdin as documented
+ * - support elf file parsing using our own elf support.
+ * - as always magdir fixes and additions.
+ *
+ * Revision 1.19  1995/10/27  23:14:46  christos
+ * Ability to parse colon separated list of magic files
+ * New LEGAL.NOTICE
+ * Various magic file changes
+ *
+ * Revision 1.18  1995/05/20  22:09:21  christos
+ * Passed incorrect argument to eatsize().
+ * Use %ld and %lx where appropriate.
+ * Remove unused variables
+ * ELF support for both big and little endian
+ * Fixes for small files again.
+ *
+ * Revision 1.17  1995/04/28  17:29:13  christos
+ * - Incorrect nroff detection fix from der Mouse
+ * - Lost and incorrect magic entries.
+ * - Added ELF stripped binary detection [in C; ugh]
+ * - Look for $MAGIC to find the magic file.
+ * - Eat trailing size specifications from numbers i.e. ignore 10L
+ * - More fixes for very short files
+ *
+ * Revision 1.16  1995/03/25  22:06:45  christos
+ * - use strtoul() where it exists.
+ * - fix sign-extend bug
+ * - try to detect tar archives before nroff files, otherwise
+ *   tar files where the first file starts with a . will not work
+ *
+ * Revision 1.15  1995/01/21  21:03:35  christos
+ * Added CSECTION for the file man page
+ * Added version flag -v
+ * Fixed bug with -f input flag (from io...@violet.berkeley.edu)
+ * Lots of magic fixes and reorganization...
+ *
+ * Revision 1.14  1994/05/03  17:58:23  christos
+ * changes from mycr...@gnu.ai.mit.edu (Charles Hannum) for unsigned
+ *
+ * Revision 1.13  1994/01/21  01:27:01  christos
+ * Fixed null termination bug from Don Seeley at BSDI in ascmagic.c
+ *
+ * Revision 1.12  1993/10/27  20:59:05  christos
+ * Changed -z flag to understand gzip format too.
+ * Moved builtin compression detection to a table, and move
+ * the compress magic entry out of the source.
+ * Made printing of numbers unsigned, and added the mask to it.
+ * Changed the buffer size to 8k, because gzip will refuse to
+ * unzip just a few bytes.
+ *
+ * Revision 1.11  1993/09/24  18:49:06  christos
+ * Fixed small bug in softmagic.c introduced by
+ * copying the data to be examined out of the input
+ * buffer. Changed the Makefile to use sed to create
+ * the correct man pages.
+ *
+ * Revision 1.10  1993/09/23  21:56:23  christos
+ * Passed purify. Fixed indirections. Fixed byte order printing.
+ * Fixed segmentation faults caused by referencing past the end
+ * of the magic buffer. Fixed bus errors caused by referencing
+ * unaligned shorts or longs.
+ *
+ * Revision 1.9  1993/03/24  14:23:40  ian
+ * Batch of minor changes from several contributors.
+ *
+ * Revision 1.8  93/02/19  15:01:26  ian
+ * Numerous changes from Guy Harris too numerous to mention but including
+ * byte-order independance, fixing "old-style masking", etc. etc. A bugfix
+ * for broken symlinks from martin@@d255s004.zfe.siemens.de.
+ * 
+ * Revision 1.7  93/01/05  14:57:27  ian
+ * Couple of nits picked by Christos (again, thanks).
+ * 
+ * Revision 1.6  93/01/05  13:51:09  ian
+ * Lotsa work on the Magic directory.
+ * 
+ * Revision 1.5  92/09/14  14:54:51  ian
+ * Fix a tiny null-pointer bug in previous fix for tar archive + uncompress.
+ * 
+ */
+
Index: src/external/gpl2/mkhybrid/dist/libfile/softmagic.c
diff -u /dev/null src/external/gpl2/mkhybrid/dist/libfile/softmagic.c:1.1
--- /dev/null	Fri May 31 19:52:25 2024
+++ src/external/gpl2/mkhybrid/dist/libfile/softmagic.c	Fri May 31 19:52:25 2024
@@ -0,0 +1,384 @@
+/* @(#)softmagic.c	1.12 09/07/11 joerg */
+#include <schily/mconfig.h>
+#ifndef lint
+static	UConst char sccsid[] =
+	"@(#)softmagic.c	1.12 09/07/11 joerg";
+#endif
+/*
+**	find file types by using a modified "magic" file
+**
+**	based on file v3.22 by Ian F. Darwin (see below)
+**
+**	Modified for mkhybrid James Pearson 19/5/98
+*/
+
+/*
+ * 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 export provision of the United States
+ * Department of Commerce, and may be exported to any country or planet.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice immediately at the beginning of the file, without modification,
+ *    this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <schily/stdio.h>
+#include <schily/string.h>
+#include <schily/stdlib.h>
+#include <schily/schily.h>
+
+#include "file.h"
+
+#ifndef	lint
+static UConst char moduleid[] = 
+	"@(#)Id: softmagic.c,v 1.34 1997/01/15 19:28:35 christos Exp";
+#endif	/* lint */
+
+#ifdef DEBUG
+int	debug = 1; 	/* debugging 				*/
+#else
+#define	debug	0 	/* debugging 				*/
+#endif /* DEBUG */
+
+/* static int match	__PR((unsigned char *, int)); */
+static char *match	__PR((unsigned char *, int));
+static int mget		__PR((union VALUETYPE *,
+			     unsigned char *, struct magic *, int));
+/* QNX has a mcheck() prototyp in a public include file */
+static int magcheck	__PR((union VALUETYPE *, struct magic *));
+#ifdef	__used__
+static void mdebug	__PR((Int32_t, char *, int));
+#endif
+static int mconvert	__PR((union VALUETYPE *, struct magic *));
+
+/*
+ * 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 */
+char *
+softmagic(buf, nbytes)
+unsigned char *buf;
+int nbytes;
+{
+	return (match(buf, nbytes));
+}
+
+/*
+ * 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.
+ */
+static char *
+match(s, nbytes)
+unsigned char	*s;
+int nbytes;
+{
+	int magindex = 0;
+	union VALUETYPE p;
+
+	for (magindex = 0; magindex < __f_nmagic; magindex++) {
+		/* if main entry matches, print it... */
+		if (!mget(&p, s, &__f_magic[magindex], nbytes) ||
+		    !magcheck(&p, &__f_magic[magindex])) {
+			    /* 
+			     * main entry didn't match,
+			     * flush its continuations
+			     */
+			    while (magindex < __f_nmagic &&
+			    	   __f_magic[magindex + 1].cont_level != 0)
+			    	   magindex++;
+			    continue;
+		}
+
+		return (__f_magic[magindex].desc);
+	}
+	return 0;			/* no match at all */
+}
+
+
+/*
+ * Convert the byte order of the data we are looking at
+ */
+static int
+mconvert(p, m)
+union VALUETYPE *p;
+struct magic *m;
+{
+	switch (m->type) {
+	case BYTE:
+	case SHORT:
+	case LONG:
+	case DATE:
+		return 1;
+	case STRING:
+		{
+			char *ptr;
+
+			/* Null terminate and eat the return */
+			p->s[sizeof(p->s) - 1] = '\0';
+			if ((ptr = strchr(p->s, '\n')) != NULL)
+				*ptr = '\0';
+			return 1;
+		}
+	case BESHORT:
+		p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
+		return 1;
+	case BELONG:
+	case BEDATE:
+		p->l = (Int32_t)
+		    ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
+		return 1;
+	case LESHORT:
+		p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
+		return 1;
+	case LELONG:
+	case LEDATE:
+		p->l = (Int32_t)
+		    ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+#ifdef	__used__
+static void
+mdebug(offset, str, len)
+Int32_t offset;
+char *str;
+int len;
+{
+	(void) fprintf(stderr, "mget @%d: ", offset);
+	showstr(stderr, (char *) str, len);
+	(void) fputc('\n', stderr);
+	(void) fputc('\n', stderr);
+}
+#endif
+
+static int
+mget(p, s, m, nbytes)
+union VALUETYPE* p;
+unsigned char	*s;
+struct magic *m;
+int nbytes;
+{
+	Int32_t offset = m->offset;
+
+	if (offset + sizeof(union VALUETYPE) <= nbytes)
+		memcpy(p, s + offset, sizeof(union VALUETYPE));
+	else {
+		/*
+		 * the usefulness of padding with zeroes eludes me, it
+		 * might even cause problems
+		 */
+		Int32_t have = nbytes - offset;
+		memset(p, 0, sizeof(union VALUETYPE));
+		if (have > 0)
+			memcpy(p, s + offset, have);
+	}
+
+	if (!mconvert(p, m))
+		return 0;
+
+	if (m->flag & INDIR) {
+
+		switch (m->in.type) {
+		case BYTE:
+			offset = p->b + m->in.offset;
+			break;
+		case SHORT:
+			offset = p->h + m->in.offset;
+			break;
+		case LONG:
+			offset = p->l + m->in.offset;
+			break;
+		}
+
+		if (offset + sizeof(union VALUETYPE) > nbytes)
+			return 0;
+
+		memcpy(p, s + offset, sizeof(union VALUETYPE));
+
+		if (!mconvert(p, m))
+			return 0;
+	}
+	return 1;
+}
+
+static int
+magcheck(p, m)
+union VALUETYPE* p;
+struct magic *m;
+{
+	register UInt32_t l = m->value.l;
+	register UInt32_t v;
+	int matched;
+
+	if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
+		fprintf(stderr, "BOINK");
+		return 1;
+	}
+
+
+	switch (m->type) {
+	case BYTE:
+		v = p->b;
+		break;
+
+	case SHORT:
+	case BESHORT:
+	case LESHORT:
+		v = p->h;
+		break;
+
+	case LONG:
+	case BELONG:
+	case LELONG:
+	case DATE:
+	case BEDATE:
+	case LEDATE:
+		v = p->l;
+		break;
+
+	case STRING:
+		l = 0;
+		/* What we want here is:
+		 * v = strncmp(m->value.s, p->s, m->vallen);
+		 * but ignoring any nulls.  bcmp doesn't give -/+/0
+		 * and isn't universally available anyway.
+		 */
+		v = 0;
+		{
+			register unsigned char *a = (unsigned char*)m->value.s;
+			register unsigned char *b = (unsigned char*)p->s;
+			register int len = m->vallen;
+
+			while (--len >= 0)
+				if ((v = *b++ - *a++) != '\0')
+					break;
+		}
+		break;
+	default:
+		return 0;/*NOTREACHED*/
+	}
+
+	v = signextend(m, v) & m->mask;
+
+	switch (m->reln) {
+	case 'x':
+		if (debug)
+			(void) fprintf(stderr, "%u == *any* = 1\n", v);
+		matched = 1;
+		break;
+
+	case '!':
+		matched = v != l;
+		if (debug)
+			(void) fprintf(stderr, "%u != %u = %d\n",
+				       v, l, matched);
+		break;
+
+	case '=':
+		matched = v == l;
+		if (debug)
+			(void) fprintf(stderr, "%u == %u = %d\n",
+				       v, l, matched);
+		break;
+
+	case '>':
+		if (m->flag & UNSIGNED) {
+			matched = v > l;
+			if (debug)
+				(void) fprintf(stderr, "%u > %u = %d\n",
+					       v, l, matched);
+		}
+		else {
+			matched = (Int32_t) v > (Int32_t) l;
+			if (debug)
+				(void) fprintf(stderr, "%d > %d = %d\n",
+					    (Int32_t)v, (Int32_t)l, matched);
+		}
+		break;
+
+	case '<':
+		if (m->flag & UNSIGNED) {
+			matched = v < l;
+			if (debug)
+				(void) fprintf(stderr, "%u < %u = %d\n",
+					       v, l, matched);
+		}
+		else {
+			matched = (Int32_t) v < (Int32_t) l;
+			if (debug)
+				(void) fprintf(stderr, "%d < %d = %d\n",
+					    (Int32_t)v, (Int32_t)l, matched);
+		}
+		break;
+
+	case '&':
+		matched = (v & l) == l;
+		if (debug)
+			(void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
+				       v, l, l, matched);
+		break;
+
+	case '^':
+		matched = (v & l) != l;
+		if (debug)
+			(void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
+				       v, l, l, matched);
+		break;
+
+	default:
+		matched = 0;
+		break;/*NOTREACHED*/
+	}
+
+	return matched;
+}

Reply via email to