xref: /onnv-gate/usr/src/cmd/file/magicutils.c (revision 3466:4cc6ca6917b5)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*3466Srie  * Common Development and Distribution License (the "License").
6*3466Srie  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3466Srie  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
300Sstevel@tonic-gate /*	  All Rights Reserved	*/
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <ctype.h>
380Sstevel@tonic-gate #include <errno.h>
390Sstevel@tonic-gate #include <limits.h>
400Sstevel@tonic-gate #include <inttypes.h>
410Sstevel@tonic-gate #include <sys/types.h>
420Sstevel@tonic-gate #include <libintl.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate  *	Types
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate 
480Sstevel@tonic-gate #define	BYTE	1
490Sstevel@tonic-gate #define	SHORT	2
500Sstevel@tonic-gate #define	LONG	4
510Sstevel@tonic-gate #define	LLONG	8
520Sstevel@tonic-gate #define	UBYTE	16
530Sstevel@tonic-gate #define	USHORT	32
540Sstevel@tonic-gate #define	ULONG	64
550Sstevel@tonic-gate #define	ULLONG	128
560Sstevel@tonic-gate #define	STR	256
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate  *	Opcodes
600Sstevel@tonic-gate  */
610Sstevel@tonic-gate 
620Sstevel@tonic-gate #define	EQ	0
630Sstevel@tonic-gate #define	GT	1
640Sstevel@tonic-gate #define	LT	2
650Sstevel@tonic-gate #define	STRC	3	/* string compare */
660Sstevel@tonic-gate #define	ANY	4
670Sstevel@tonic-gate #define	AND	5
680Sstevel@tonic-gate #define	NSET	6	/* True if bit is not set */
690Sstevel@tonic-gate #define	SUB	64	/* or'ed in, SUBstitution string, for example */
700Sstevel@tonic-gate 			/* %ld, %s, %lo mask: with bit 6 on, used to locate */
710Sstevel@tonic-gate 			/* print formats */
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate  *	Misc
740Sstevel@tonic-gate  */
750Sstevel@tonic-gate 
760Sstevel@tonic-gate #define	BSZ	128
770Sstevel@tonic-gate #define	NENT	200
780Sstevel@tonic-gate 
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate  *	Structure of magic file entry
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate 
830Sstevel@tonic-gate struct	entry	{
840Sstevel@tonic-gate 	char		e_level;	/* 0 or 1 */
850Sstevel@tonic-gate 	off_t		e_off;		/* in bytes */
860Sstevel@tonic-gate 	uint32_t	e_type;		/* BYTE, SHORT, STR, et al */
870Sstevel@tonic-gate 	char		e_opcode;	/* EQ, GT, LT, ANY, AND, NSET */
880Sstevel@tonic-gate 	uint64_t	e_mask;		/* if non-zero, mask value with this */
890Sstevel@tonic-gate 	union	{
900Sstevel@tonic-gate 		uint64_t	num;
910Sstevel@tonic-gate 		char		*str;
920Sstevel@tonic-gate 	}	e_value;
930Sstevel@tonic-gate 	const char	*e_str;
940Sstevel@tonic-gate };
950Sstevel@tonic-gate 
96*3466Srie /* Non-localized string giving name of command.  Defined in file.c */
97*3466Srie extern const char	*File;
98*3466Srie 
990Sstevel@tonic-gate typedef	struct entry	Entry;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate static Entry	*mtab1;	/* 1st magic table, applied before default tests */
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	/*
1040Sstevel@tonic-gate 	 * 2nd magic table, includes default tests and magic entries
1050Sstevel@tonic-gate 	 * to be applied after default position-sensitive tests
1060Sstevel@tonic-gate 	 */
1070Sstevel@tonic-gate static Entry	*mtab2;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate static Entry	*mend1;	/* one past last-allocated entry in mtab1 */
1100Sstevel@tonic-gate static Entry	*mend2;	/* one past last-allocated entry in mtab2 */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate static Entry	*ep1;	/* current entry in mtab1 */
1130Sstevel@tonic-gate static Entry	*ep2;	/* current entry in mtab2 */
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate static char *
getstr(char * p,char * file)116*3466Srie getstr(char *p, char *file)
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate 	char	*newstr;
1190Sstevel@tonic-gate 	char	*s;
1200Sstevel@tonic-gate 	long	val;
1210Sstevel@tonic-gate 	int	base;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	newstr = (char *)malloc((strlen(p) + 1) * sizeof (char));
1240Sstevel@tonic-gate 	if (newstr == NULL) {
125*3466Srie 		int err = errno;
126*3466Srie 		(void) fprintf(stderr, gettext("%s: malloc failed: %s\n"),
127*3466Srie 		    File, strerror(err));
1280Sstevel@tonic-gate 		return (NULL);
1290Sstevel@tonic-gate 	}
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	s = newstr;
1320Sstevel@tonic-gate 	while (*p != '\0') {
1330Sstevel@tonic-gate 		if (*p != '\\') {
1340Sstevel@tonic-gate 			*s++ = *p++;
1350Sstevel@tonic-gate 			continue;
1360Sstevel@tonic-gate 		}
1370Sstevel@tonic-gate 		p++;
1380Sstevel@tonic-gate 		if (*p == '\0')
1390Sstevel@tonic-gate 			break;
1400Sstevel@tonic-gate 		if (isdigit(*p)) {
1410Sstevel@tonic-gate 			if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) {
1420Sstevel@tonic-gate 				/* hex */
1430Sstevel@tonic-gate 				base = 16;
1440Sstevel@tonic-gate 			} else {
1450Sstevel@tonic-gate 				base = 8;
1460Sstevel@tonic-gate 			}
1470Sstevel@tonic-gate 			errno = 0;
1480Sstevel@tonic-gate 			val = strtol(p, &p, base);
1490Sstevel@tonic-gate 			if (val > UCHAR_MAX || val < 0 || errno != 0) {
150*3466Srie 				(void) fprintf(stderr, gettext("%s: %s: magic "
151*3466Srie 				    "table invalid string value\n"), File,
152*3466Srie 				    file);
1530Sstevel@tonic-gate 				return (NULL);
1540Sstevel@tonic-gate 			}
1550Sstevel@tonic-gate 			*s++ = (char)val;
1560Sstevel@tonic-gate 		} else {
1570Sstevel@tonic-gate 			/* escape the character */
1580Sstevel@tonic-gate 			switch (*p) {
1590Sstevel@tonic-gate 			case 'n':
1600Sstevel@tonic-gate 				*s = '\n';
1610Sstevel@tonic-gate 				break;
1620Sstevel@tonic-gate 			case 'r':
1630Sstevel@tonic-gate 				*s = '\r';
1640Sstevel@tonic-gate 				break;
1650Sstevel@tonic-gate 			case 'a':
1660Sstevel@tonic-gate 				*s = '\a';
1670Sstevel@tonic-gate 				break;
1680Sstevel@tonic-gate 			case 'b':
1690Sstevel@tonic-gate 				*s = '\b';
1700Sstevel@tonic-gate 				break;
1710Sstevel@tonic-gate 			case 'f':
1720Sstevel@tonic-gate 				*s = '\f';
1730Sstevel@tonic-gate 				break;
1740Sstevel@tonic-gate 			case 't':
1750Sstevel@tonic-gate 				*s = '\t';
1760Sstevel@tonic-gate 				break;
1770Sstevel@tonic-gate 			case 'v':
1780Sstevel@tonic-gate 				*s = '\v';
1790Sstevel@tonic-gate 				break;
1800Sstevel@tonic-gate 			default:
1810Sstevel@tonic-gate 				*s = *p;
1820Sstevel@tonic-gate 				break;
1830Sstevel@tonic-gate 			}
1840Sstevel@tonic-gate 			p++;
1850Sstevel@tonic-gate 			s++;
1860Sstevel@tonic-gate 		}
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 	*s = '\0';
1890Sstevel@tonic-gate 	return (newstr);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate  * f_mkmtab - fills mtab array of magic table entries with
1940Sstevel@tonic-gate  *	values from the file magfile.
1950Sstevel@tonic-gate  *	May be called more than once if multiple magic
1960Sstevel@tonic-gate  * 	files were specified.
1970Sstevel@tonic-gate  *	Stores entries sequentially in one of two magic
1980Sstevel@tonic-gate  *	tables: mtab1, if first = 1; mtab2 otherwise.
1990Sstevel@tonic-gate  *
2000Sstevel@tonic-gate  *	If -c option is specified, cflg is non-zero, and
2010Sstevel@tonic-gate  *	f_mkmtab() reports on errors in the magic file.
2020Sstevel@tonic-gate  *
2030Sstevel@tonic-gate  *	Two magic tables may need to be created.  The first
2040Sstevel@tonic-gate  *	one (mtab1) contains magic entries to be checked before
2050Sstevel@tonic-gate  *	the programmatic default position-sensitive tests in
2060Sstevel@tonic-gate  *	def_position_tests().
2070Sstevel@tonic-gate  *	The second one (mtab2) should start with the default
2080Sstevel@tonic-gate  *	/etc/magic file entries and is to be checked after
2090Sstevel@tonic-gate  *	the programmatic default position-sensitive tests in
2100Sstevel@tonic-gate  *	def_position_tests().  The parameter "first" would
2110Sstevel@tonic-gate  *	be 1 for the former set of tables, 0 for the latter
2120Sstevel@tonic-gate  *	set of magic tables.
2130Sstevel@tonic-gate  *	No mtab2 should be created if file will not be
2140Sstevel@tonic-gate  *	applying default tests; in that case, all magic table
2150Sstevel@tonic-gate  *	entries should be in mtab1.
2160Sstevel@tonic-gate  *
2170Sstevel@tonic-gate  *	f_mkmtab returns 0 on success, -1 on error.  The calling
2180Sstevel@tonic-gate  *	program is not expected to proceed after f_mkmtab()
2190Sstevel@tonic-gate  *	returns an error.
2200Sstevel@tonic-gate  */
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate int
f_mkmtab(char * magfile,int cflg,int first)2230Sstevel@tonic-gate f_mkmtab(char *magfile, int cflg, int first)
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate 	Entry	*mtab;	/* generic magic table pointer */
2260Sstevel@tonic-gate 	Entry	*ep;	/* current magic table entry */
2270Sstevel@tonic-gate 	Entry	*mend;	/* one past last-allocated entry of mtab */
2280Sstevel@tonic-gate 	FILE	*fp;
2290Sstevel@tonic-gate 	int	lcnt = 0;
2300Sstevel@tonic-gate 	char	buf[BSZ];
2310Sstevel@tonic-gate 	size_t	tbsize;
2320Sstevel@tonic-gate 	size_t	oldsize;
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	if (first) {
2350Sstevel@tonic-gate 		mtab = mtab1;
2360Sstevel@tonic-gate 		mend = mend1;
2370Sstevel@tonic-gate 		ep = ep1;
2380Sstevel@tonic-gate 	} else {
2390Sstevel@tonic-gate 		mtab = mtab2;
2400Sstevel@tonic-gate 		mend = mend2;
2410Sstevel@tonic-gate 		ep = ep2;
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	/* mtab may have been allocated on a previous f_mkmtab call */
2450Sstevel@tonic-gate 	if (mtab == (Entry *)NULL) {
246*3466Srie 		if ((mtab = calloc(sizeof (Entry), NENT)) == NULL) {
247*3466Srie 			int err = errno;
248*3466Srie 			(void) fprintf(stderr, gettext("%s: malloc "
249*3466Srie 			    "failed: %s\n"), File, strerror(err));
2500Sstevel@tonic-gate 			return (-1);
2510Sstevel@tonic-gate 		}
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 		ep = mtab;
2540Sstevel@tonic-gate 		mend = &mtab[NENT];
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 
257*3466Srie 	errno = 0;
258*3466Srie 	if ((fp = fopen(magfile, "r")) == NULL) {
259*3466Srie 		int err = errno;
260*3466Srie 		(void) fprintf(stderr, gettext("%s: %s: cannot open magic "
261*3466Srie 		    "file: %s\n"), File, magfile, err ? strerror(err) : "");
2620Sstevel@tonic-gate 		return (-1);
2630Sstevel@tonic-gate 	}
2640Sstevel@tonic-gate 	while (fgets(buf, BSZ, fp) != NULL) {
2650Sstevel@tonic-gate 		char	*p = buf;
2660Sstevel@tonic-gate 		char	*p2;
2670Sstevel@tonic-gate 		char	*p3;
2680Sstevel@tonic-gate 		char	opc;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 		/*
2710Sstevel@tonic-gate 		 * ensure we have one extra entry allocated
2720Sstevel@tonic-gate 		 * to mark end of the table, after the while loop
2730Sstevel@tonic-gate 		 */
2740Sstevel@tonic-gate 		if (ep >= (mend - 1)) {
2750Sstevel@tonic-gate 			oldsize = mend - mtab;
2760Sstevel@tonic-gate 			tbsize = (NENT + oldsize) * sizeof (Entry);
2770Sstevel@tonic-gate 			if ((mtab = realloc(mtab, tbsize)) == NULL) {
278*3466Srie 				int err = errno;
279*3466Srie 				(void) fprintf(stderr, gettext("%s: malloc "
280*3466Srie 				    "failed: %s\n"), File, strerror(err));
2810Sstevel@tonic-gate 				return (-1);
2820Sstevel@tonic-gate 			} else {
2830Sstevel@tonic-gate 				(void) memset(mtab + oldsize, 0,
2840Sstevel@tonic-gate 				    sizeof (Entry) * NENT);
2850Sstevel@tonic-gate 				mend = &mtab[tbsize / sizeof (Entry)];
2860Sstevel@tonic-gate 				ep = &mtab[oldsize-1];
2870Sstevel@tonic-gate 			}
2880Sstevel@tonic-gate 		}
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 		lcnt++;
2910Sstevel@tonic-gate 		if (*p == '\n' || *p == '#')
2920Sstevel@tonic-gate 			continue;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 			/* LEVEL */
2960Sstevel@tonic-gate 		if (*p == '>') {
2970Sstevel@tonic-gate 			ep->e_level = 1;
2980Sstevel@tonic-gate 			p++;
2990Sstevel@tonic-gate 		}
3000Sstevel@tonic-gate 			/* OFFSET */
3010Sstevel@tonic-gate 		p2 = strchr(p, '\t');
3020Sstevel@tonic-gate 		if (p2 == NULL) {
3030Sstevel@tonic-gate 			if (cflg)
304*3466Srie 				(void) fprintf(stderr, gettext("%s: %s: format "
305*3466Srie 				    "error, no tab after %s on line %d\n"),
306*3466Srie 				    File, magfile, p, lcnt);
3070Sstevel@tonic-gate 			continue;
3080Sstevel@tonic-gate 		}
3090Sstevel@tonic-gate 		*p2++ = NULL;
3100Sstevel@tonic-gate 		ep->e_off = strtol((const char *)p, (char **)NULL, 0);
3110Sstevel@tonic-gate 		while (*p2 == '\t')
3120Sstevel@tonic-gate 			p2++;
3130Sstevel@tonic-gate 			/* TYPE */
3140Sstevel@tonic-gate 		p = p2;
3150Sstevel@tonic-gate 		p2 = strchr(p, '\t');
3160Sstevel@tonic-gate 		if (p2 == NULL) {
3170Sstevel@tonic-gate 			if (cflg)
318*3466Srie 				(void) fprintf(stderr, gettext("%s: %s: format "
319*3466Srie 				    "error, no tab after %s on line %d\n"),
320*3466Srie 				    File, magfile, p, lcnt);
3210Sstevel@tonic-gate 			continue;
3220Sstevel@tonic-gate 		}
3230Sstevel@tonic-gate 		*p2++ = NULL;
3240Sstevel@tonic-gate 		p3 = strchr(p, '&');
3250Sstevel@tonic-gate 		if (p3 != NULL) {
3260Sstevel@tonic-gate 			*p3++ = '\0';
3270Sstevel@tonic-gate 			ep->e_mask = strtoull((const char *)p3, (char **)NULL,
3280Sstevel@tonic-gate 			    0);	/* returns 0 or ULLONG_MAX on error */
3290Sstevel@tonic-gate 		} else {
3300Sstevel@tonic-gate 			ep->e_mask = 0ULL;
3310Sstevel@tonic-gate 		}
3320Sstevel@tonic-gate 		switch (*p) {
3330Sstevel@tonic-gate 			case 'd':
3340Sstevel@tonic-gate 				if (*(p+1) == NULL) {
3350Sstevel@tonic-gate 					/* d */
3360Sstevel@tonic-gate 					ep->e_type = LONG;
3370Sstevel@tonic-gate 				} else if (*(p+2) == NULL) {	/* d? */
3380Sstevel@tonic-gate 					switch (*(p+1)) {
3390Sstevel@tonic-gate 						case 'C':
3400Sstevel@tonic-gate 						case '1':
3410Sstevel@tonic-gate 							/* dC, d1 */
3420Sstevel@tonic-gate 							ep->e_type = BYTE;
3430Sstevel@tonic-gate 							break;
3440Sstevel@tonic-gate 						case 'S':
3450Sstevel@tonic-gate 						case '2':
3460Sstevel@tonic-gate 							/* dS, d2 */
3470Sstevel@tonic-gate 							ep->e_type = SHORT;
3480Sstevel@tonic-gate 							break;
3490Sstevel@tonic-gate 						case 'I':
3500Sstevel@tonic-gate 						case 'L':
3510Sstevel@tonic-gate 						case '4':
3520Sstevel@tonic-gate 							/* dI, dL, d4 */
3530Sstevel@tonic-gate 							ep->e_type = LONG;
3540Sstevel@tonic-gate 							break;
3550Sstevel@tonic-gate 						case '8':
3560Sstevel@tonic-gate 							/* d8 */
3570Sstevel@tonic-gate 							ep->e_type = LLONG;
3580Sstevel@tonic-gate 							break;
3590Sstevel@tonic-gate 						default:
3600Sstevel@tonic-gate 							ep->e_type = LONG;
3610Sstevel@tonic-gate 							break;
3620Sstevel@tonic-gate 					}
3630Sstevel@tonic-gate 				}
3640Sstevel@tonic-gate 				break;
3650Sstevel@tonic-gate 			case 'l':
3660Sstevel@tonic-gate 				if (*(p+1) == 'l') {	/* llong */
3670Sstevel@tonic-gate 					ep->e_type = LLONG;
3680Sstevel@tonic-gate 				} else { 		/* long */
3690Sstevel@tonic-gate 					ep->e_type = LONG;
3700Sstevel@tonic-gate 				}
3710Sstevel@tonic-gate 				break;
3720Sstevel@tonic-gate 			case 's':
3730Sstevel@tonic-gate 				if (*(p+1) == 'h') {
3740Sstevel@tonic-gate 					/* short */
3750Sstevel@tonic-gate 					ep->e_type = SHORT;
3760Sstevel@tonic-gate 				} else {
3770Sstevel@tonic-gate 					/* s or string */
3780Sstevel@tonic-gate 					ep->e_type = STR;
3790Sstevel@tonic-gate 				}
3800Sstevel@tonic-gate 				break;
3810Sstevel@tonic-gate 			case 'u':
3820Sstevel@tonic-gate 				if (*(p+1) == NULL) {
3830Sstevel@tonic-gate 					/* u */
3840Sstevel@tonic-gate 					ep->e_type = ULONG;
3850Sstevel@tonic-gate 				} else if (*(p+2) == NULL) {	/* u? */
3860Sstevel@tonic-gate 					switch (*(p+1)) {
3870Sstevel@tonic-gate 						case 'C':
3880Sstevel@tonic-gate 						case '1':
3890Sstevel@tonic-gate 							/* uC, u1 */
3900Sstevel@tonic-gate 							ep->e_type = UBYTE;
3910Sstevel@tonic-gate 							break;
3920Sstevel@tonic-gate 						case 'S':
3930Sstevel@tonic-gate 						case '2':
3940Sstevel@tonic-gate 							/* uS, u2 */
3950Sstevel@tonic-gate 							ep->e_type = USHORT;
3960Sstevel@tonic-gate 							break;
3970Sstevel@tonic-gate 						case 'I':
3980Sstevel@tonic-gate 						case 'L':
3990Sstevel@tonic-gate 						case '4':
4000Sstevel@tonic-gate 							/* uI, uL, u4 */
4010Sstevel@tonic-gate 							ep->e_type = ULONG;
4020Sstevel@tonic-gate 							break;
4030Sstevel@tonic-gate 						case '8':
4040Sstevel@tonic-gate 							/* u8 */
4050Sstevel@tonic-gate 							ep->e_type = ULLONG;
4060Sstevel@tonic-gate 							break;
4070Sstevel@tonic-gate 						default:
4080Sstevel@tonic-gate 							ep->e_type = ULONG;
4090Sstevel@tonic-gate 							break;
4100Sstevel@tonic-gate 					}
4110Sstevel@tonic-gate 				} else { /* u?* */
4120Sstevel@tonic-gate 					switch (*(p+1)) {
4130Sstevel@tonic-gate 					case 'b':	/* ubyte */
4140Sstevel@tonic-gate 						ep->e_type = UBYTE;
4150Sstevel@tonic-gate 						break;
4160Sstevel@tonic-gate 					case 's':	/* ushort */
4170Sstevel@tonic-gate 						ep->e_type = USHORT;
4180Sstevel@tonic-gate 						break;
4190Sstevel@tonic-gate 					case 'l':
4200Sstevel@tonic-gate 						if (*(p+2) == 'l') {
4210Sstevel@tonic-gate 							/* ullong */
4220Sstevel@tonic-gate 							ep->e_type = ULLONG;
4230Sstevel@tonic-gate 						} else {
4240Sstevel@tonic-gate 							/* ulong */
4250Sstevel@tonic-gate 							ep->e_type = ULONG;
4260Sstevel@tonic-gate 						}
4270Sstevel@tonic-gate 						break;
4280Sstevel@tonic-gate 					default:
4290Sstevel@tonic-gate 						/* default, same as "u" */
4300Sstevel@tonic-gate 						ep->e_type = ULONG;
4310Sstevel@tonic-gate 						break;
4320Sstevel@tonic-gate 					}
4330Sstevel@tonic-gate 				}
4340Sstevel@tonic-gate 				break;
4350Sstevel@tonic-gate 			default:
4360Sstevel@tonic-gate 				/* retain (undocumented) default type */
4370Sstevel@tonic-gate 				ep->e_type = BYTE;
4380Sstevel@tonic-gate 				break;
4390Sstevel@tonic-gate 		}
4400Sstevel@tonic-gate 		if (ep->e_type == 0) {
4410Sstevel@tonic-gate 			ep->e_type = BYTE;	/* default */
4420Sstevel@tonic-gate 		}
4430Sstevel@tonic-gate 		while (*p2 == '\t')
4440Sstevel@tonic-gate 			p2++;
4450Sstevel@tonic-gate 			/* OP-VALUE */
4460Sstevel@tonic-gate 		p = p2;
4470Sstevel@tonic-gate 		p2 = strchr(p, '\t');
4480Sstevel@tonic-gate 		if (p2 == NULL) {
4490Sstevel@tonic-gate 			if (cflg)
450*3466Srie 				(void) fprintf(stderr, gettext("%s: %s: format "
451*3466Srie 				    "error, no tab after %s on line %d\n"),
452*3466Srie 				    File, magfile, p, lcnt);
4530Sstevel@tonic-gate 			continue;
4540Sstevel@tonic-gate 		}
4550Sstevel@tonic-gate 		*p2++ = NULL;
4560Sstevel@tonic-gate 		if (ep->e_type != STR) {
4570Sstevel@tonic-gate 			opc = *p++;
4580Sstevel@tonic-gate 			switch (opc) {
4590Sstevel@tonic-gate 			case '=':
4600Sstevel@tonic-gate 				ep->e_opcode = EQ;
4610Sstevel@tonic-gate 				break;
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 			case '>':
4640Sstevel@tonic-gate 				ep->e_opcode = GT;
4650Sstevel@tonic-gate 				break;
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 			case '<':
4680Sstevel@tonic-gate 				ep->e_opcode = LT;
4690Sstevel@tonic-gate 				break;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 			case 'x':
4720Sstevel@tonic-gate 				ep->e_opcode = ANY;
4730Sstevel@tonic-gate 				break;
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 			case '&':
4760Sstevel@tonic-gate 				ep->e_opcode = AND;
4770Sstevel@tonic-gate 				break;
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 			case '^':
4800Sstevel@tonic-gate 				ep->e_opcode = NSET;
4810Sstevel@tonic-gate 				break;
4820Sstevel@tonic-gate 			default:	/* EQ (i.e. 0) is default	*/
4830Sstevel@tonic-gate 				p--;	/* since global ep->e_opcode=0	*/
4840Sstevel@tonic-gate 			}
4850Sstevel@tonic-gate 		}
4860Sstevel@tonic-gate 		if (ep->e_opcode != ANY) {
4870Sstevel@tonic-gate 			if (ep->e_type != STR) {
4880Sstevel@tonic-gate 				ep->e_value.num = strtoull((const char *)p,
4890Sstevel@tonic-gate 				    (char **)NULL, 0);
490*3466Srie 			} else if ((ep->e_value.str =
491*3466Srie 			    getstr(p, magfile)) == NULL) {
4920Sstevel@tonic-gate 				return (-1);
4930Sstevel@tonic-gate 			}
4940Sstevel@tonic-gate 		}
4950Sstevel@tonic-gate 		p2 += strspn(p2, "\t");
4960Sstevel@tonic-gate 			/* STRING */
4970Sstevel@tonic-gate 		if ((ep->e_str = strdup(p2)) == NULL) {
498*3466Srie 			int err = errno;
499*3466Srie 			(void) fprintf(stderr, gettext("%s: malloc "
500*3466Srie 			    "failed: %s\n"), File, strerror(err));
5010Sstevel@tonic-gate 			return (-1);
5020Sstevel@tonic-gate 		} else {
5030Sstevel@tonic-gate 			if ((p = strchr(ep->e_str, '\n')) != NULL)
5040Sstevel@tonic-gate 				*p = '\0';
5050Sstevel@tonic-gate 			if (strchr(ep->e_str, '%') != NULL)
5060Sstevel@tonic-gate 				ep->e_opcode |= SUB;
5070Sstevel@tonic-gate 		}
5080Sstevel@tonic-gate 		ep++;
5090Sstevel@tonic-gate 	}	/* end while (fgets) */
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	ep->e_off = -1L;	/* mark end of table */
5120Sstevel@tonic-gate 	if (first) {
5130Sstevel@tonic-gate 		mtab1 = mtab;
5140Sstevel@tonic-gate 		mend1 = mend;
5150Sstevel@tonic-gate 		ep1 = ep;
5160Sstevel@tonic-gate 	} else {
5170Sstevel@tonic-gate 		mtab2 = mtab;
5180Sstevel@tonic-gate 		mend2 = mend;
5190Sstevel@tonic-gate 		ep2 = ep;
5200Sstevel@tonic-gate 	}
521*3466Srie 	if (fclose(fp) != 0) {
522*3466Srie 		int err = errno;
523*3466Srie 		(void) fprintf(stderr, gettext("%s: fclose failed: %s\n"),
524*3466Srie 		    File, strerror(err));
5250Sstevel@tonic-gate 		return (-1);
5260Sstevel@tonic-gate 	}
5270Sstevel@tonic-gate 	return (0);
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate  * Check for Magic Table entries in the file.
5320Sstevel@tonic-gate  *
5330Sstevel@tonic-gate  * Since there may be two sets of magic tables, first = 1
5340Sstevel@tonic-gate  * for the first magic table (mtab1) and 0 for the second magic
5350Sstevel@tonic-gate  * table (mtab2).
5360Sstevel@tonic-gate  */
5370Sstevel@tonic-gate int
f_ckmtab(char * buf,int bufsize,int first)5380Sstevel@tonic-gate f_ckmtab(char *buf, int bufsize, int first)
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate 	int 		result;
5410Sstevel@tonic-gate 	Entry		*mtab;
5420Sstevel@tonic-gate 	Entry		*ep;
5430Sstevel@tonic-gate 	char		*p;
5440Sstevel@tonic-gate 	int		lev1 = 0;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	uint16_t	u16_val;
5470Sstevel@tonic-gate 	uint32_t	u32_val;
5480Sstevel@tonic-gate 	uint64_t	u64_val;
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	if (first) {
5510Sstevel@tonic-gate 		mtab = mtab1;
5520Sstevel@tonic-gate 	} else {
5530Sstevel@tonic-gate 		mtab = mtab2;
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	if (mtab == (Entry *)NULL) {
5570Sstevel@tonic-gate 		return (0);	/* no magic file tests in this table */
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	for (ep = mtab; ep->e_off != -1L; ep++) {  /* -1 offset marks end of */
5610Sstevel@tonic-gate 		if (lev1) {			/* valid magic file entries */
5620Sstevel@tonic-gate 			if (ep->e_level != 1)
5630Sstevel@tonic-gate 				break;
5640Sstevel@tonic-gate 		} else if (ep->e_level == 1) {
5650Sstevel@tonic-gate 			continue;
5660Sstevel@tonic-gate 		}
5670Sstevel@tonic-gate 		if (ep->e_off > (off_t)bufsize)
5680Sstevel@tonic-gate 			continue;
5690Sstevel@tonic-gate 		p = &buf[ep->e_off];
5700Sstevel@tonic-gate 		switch (ep->e_type) {
5710Sstevel@tonic-gate 		case STR:
5720Sstevel@tonic-gate 		{
5730Sstevel@tonic-gate 			if (strncmp(p, ep->e_value.str,
5740Sstevel@tonic-gate 			    strlen(ep->e_value.str)))
5750Sstevel@tonic-gate 				continue;
5760Sstevel@tonic-gate 			if (lev1) {
5770Sstevel@tonic-gate 				(void) putchar(' ');
5780Sstevel@tonic-gate 			}
5790Sstevel@tonic-gate 			if (ep->e_opcode & SUB)
5800Sstevel@tonic-gate 				(void) printf(ep->e_str,
5810Sstevel@tonic-gate 				    ep->e_value.str);
5820Sstevel@tonic-gate 			else
5830Sstevel@tonic-gate 				(void) printf(ep->e_str);
5840Sstevel@tonic-gate 			lev1 = 1;
5850Sstevel@tonic-gate 			continue;
5860Sstevel@tonic-gate 			/*
5870Sstevel@tonic-gate 			 * We've matched the string and printed the message;
5880Sstevel@tonic-gate 			 * no STR processing occurs beyond this point.
5890Sstevel@tonic-gate 			 */
5900Sstevel@tonic-gate 		}
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 		case BYTE:
5930Sstevel@tonic-gate 		case UBYTE:
5940Sstevel@tonic-gate 			u64_val = (uint64_t)(uint8_t)(*p);
5950Sstevel@tonic-gate 			break;
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 		case SHORT:
5980Sstevel@tonic-gate 		case USHORT:
5990Sstevel@tonic-gate 			(void) memcpy(&u16_val, p, sizeof (uint16_t));
6000Sstevel@tonic-gate 			u64_val = (uint64_t)u16_val;
6010Sstevel@tonic-gate 			break;
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 		case LONG:
6040Sstevel@tonic-gate 		case ULONG:
6050Sstevel@tonic-gate 			(void) memcpy(&u32_val, p, sizeof (uint32_t));
6060Sstevel@tonic-gate 			u64_val = (uint64_t)u32_val;
6070Sstevel@tonic-gate 			break;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 		case LLONG:
6100Sstevel@tonic-gate 		case ULLONG:
6110Sstevel@tonic-gate 			(void) memcpy(&(u64_val), p, sizeof (uint64_t));
6120Sstevel@tonic-gate 			break;
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 		}
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 		if (ep->e_mask) {
6170Sstevel@tonic-gate 			u64_val &= ep->e_mask;
6180Sstevel@tonic-gate 		}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 		/*
6210Sstevel@tonic-gate 		 * Compare the values according to the size and sign
6220Sstevel@tonic-gate 		 * of the type.  For =, &, and ^ operators, the sign
6230Sstevel@tonic-gate 		 * does not have any effect, so these are always compared
6240Sstevel@tonic-gate 		 * unsigned.  Only for < and > operators is the
6250Sstevel@tonic-gate 		 * sign significant.
6260Sstevel@tonic-gate 		 * If the file value was masked, the compare should
6270Sstevel@tonic-gate 		 * be unsigned.
6280Sstevel@tonic-gate 		 */
6290Sstevel@tonic-gate 		switch (ep->e_opcode & ~SUB) {
6300Sstevel@tonic-gate 		case EQ:
6310Sstevel@tonic-gate 			switch (ep->e_type) {
6320Sstevel@tonic-gate 			case BYTE:
6330Sstevel@tonic-gate 			case UBYTE:
6340Sstevel@tonic-gate 				if ((uint8_t)u64_val !=
6350Sstevel@tonic-gate 				    (uint8_t)(ep->e_value.num))
6360Sstevel@tonic-gate 					continue;
6370Sstevel@tonic-gate 				break;
6380Sstevel@tonic-gate 			case SHORT:
6390Sstevel@tonic-gate 			case USHORT:
6400Sstevel@tonic-gate 				if ((uint16_t)u64_val !=
6410Sstevel@tonic-gate 				    (uint16_t)(ep->e_value.num))
6420Sstevel@tonic-gate 					continue;
6430Sstevel@tonic-gate 				break;
6440Sstevel@tonic-gate 			case LONG:
6450Sstevel@tonic-gate 			case ULONG:
6460Sstevel@tonic-gate 				if ((uint32_t)u64_val !=
6470Sstevel@tonic-gate 				    (uint32_t)(ep->e_value.num))
6480Sstevel@tonic-gate 					continue;
6490Sstevel@tonic-gate 				break;
6500Sstevel@tonic-gate 			case LLONG:
6510Sstevel@tonic-gate 			case ULLONG:
6520Sstevel@tonic-gate 				if (u64_val != ep->e_value.num)
6530Sstevel@tonic-gate 					continue;
6540Sstevel@tonic-gate 				break;
6550Sstevel@tonic-gate 			default:
6560Sstevel@tonic-gate 				continue;
6570Sstevel@tonic-gate 			}
6580Sstevel@tonic-gate 			break;
6590Sstevel@tonic-gate 		case GT:
6600Sstevel@tonic-gate 			switch (ep->e_type) {
6610Sstevel@tonic-gate 			case BYTE:
6620Sstevel@tonic-gate 				if (ep->e_mask == 0) {
6630Sstevel@tonic-gate 					if ((int8_t)u64_val <=
6640Sstevel@tonic-gate 					    (int8_t)(ep->e_value.num))
6650Sstevel@tonic-gate 						continue;
6660Sstevel@tonic-gate 					break;
6670Sstevel@tonic-gate 				}
6680Sstevel@tonic-gate 				/*FALLTHROUGH*/
6690Sstevel@tonic-gate 			case UBYTE:
6700Sstevel@tonic-gate 				if ((uint8_t)u64_val <=
6710Sstevel@tonic-gate 				    (uint8_t)(ep->e_value.num))
6720Sstevel@tonic-gate 					continue;
6730Sstevel@tonic-gate 				break;
6740Sstevel@tonic-gate 			case SHORT:
6750Sstevel@tonic-gate 				if (ep->e_mask == 0) {
6760Sstevel@tonic-gate 					if ((int16_t)u64_val <=
6770Sstevel@tonic-gate 					    (int16_t)(ep->e_value.num))
6780Sstevel@tonic-gate 						continue;
6790Sstevel@tonic-gate 					break;
6800Sstevel@tonic-gate 				}
6810Sstevel@tonic-gate 				/*FALLTHROUGH*/
6820Sstevel@tonic-gate 			case USHORT:
6830Sstevel@tonic-gate 				if ((uint16_t)u64_val <=
6840Sstevel@tonic-gate 				    (uint16_t)(ep->e_value.num))
6850Sstevel@tonic-gate 					continue;
6860Sstevel@tonic-gate 				break;
6870Sstevel@tonic-gate 			case LONG:
6880Sstevel@tonic-gate 				if (ep->e_mask == 0) {
6890Sstevel@tonic-gate 					if ((int32_t)u64_val <=
6900Sstevel@tonic-gate 					    (int32_t)(ep->e_value.num))
6910Sstevel@tonic-gate 						continue;
6920Sstevel@tonic-gate 					break;
6930Sstevel@tonic-gate 				}
6940Sstevel@tonic-gate 				/*FALLTHROUGH*/
6950Sstevel@tonic-gate 			case ULONG:
6960Sstevel@tonic-gate 				if ((uint32_t)u64_val <=
6970Sstevel@tonic-gate 				    (uint32_t)(ep->e_value.num))
6980Sstevel@tonic-gate 					continue;
6990Sstevel@tonic-gate 				break;
7000Sstevel@tonic-gate 			case LLONG:
7010Sstevel@tonic-gate 				if (ep->e_mask == 0) {
7020Sstevel@tonic-gate 					if ((int64_t)u64_val <=
7030Sstevel@tonic-gate 					    (int64_t)(ep->e_value.num))
7040Sstevel@tonic-gate 						continue;
7050Sstevel@tonic-gate 					break;
7060Sstevel@tonic-gate 				}
7070Sstevel@tonic-gate 				/*FALLTHROUGH*/
7080Sstevel@tonic-gate 			case ULLONG:
7090Sstevel@tonic-gate 				if (u64_val <= ep->e_value.num)
7100Sstevel@tonic-gate 					continue;
7110Sstevel@tonic-gate 				break;
7120Sstevel@tonic-gate 			default:
7130Sstevel@tonic-gate 				continue;
7140Sstevel@tonic-gate 			}
7150Sstevel@tonic-gate 			break;
7160Sstevel@tonic-gate 		case LT:
7170Sstevel@tonic-gate 			switch (ep->e_type) {
7180Sstevel@tonic-gate 			case BYTE:
7190Sstevel@tonic-gate 				if (ep->e_mask == 0) {
7200Sstevel@tonic-gate 					if ((int8_t)u64_val >=
7210Sstevel@tonic-gate 					    (int8_t)(ep->e_value.num))
7220Sstevel@tonic-gate 						continue;
7230Sstevel@tonic-gate 					break;
7240Sstevel@tonic-gate 				}
7250Sstevel@tonic-gate 				/*FALLTHROUGH*/
7260Sstevel@tonic-gate 			case UBYTE:
7270Sstevel@tonic-gate 				if ((uint8_t)u64_val >=
7280Sstevel@tonic-gate 				    (uint8_t)(ep->e_value.num))
7290Sstevel@tonic-gate 					continue;
7300Sstevel@tonic-gate 				break;
7310Sstevel@tonic-gate 			case SHORT:
7320Sstevel@tonic-gate 				if (ep->e_mask == 0) {
7330Sstevel@tonic-gate 					if ((int16_t)u64_val >=
7340Sstevel@tonic-gate 					    (int16_t)(ep->e_value.num))
7350Sstevel@tonic-gate 						continue;
7360Sstevel@tonic-gate 					break;
7370Sstevel@tonic-gate 				}
7380Sstevel@tonic-gate 				/*FALLTHROUGH*/
7390Sstevel@tonic-gate 			case USHORT:
7400Sstevel@tonic-gate 				if ((uint16_t)u64_val >=
7410Sstevel@tonic-gate 				    (uint16_t)(ep->e_value.num))
7420Sstevel@tonic-gate 					continue;
7430Sstevel@tonic-gate 				break;
7440Sstevel@tonic-gate 			case LONG:
7450Sstevel@tonic-gate 				if (ep->e_mask == 0) {
7460Sstevel@tonic-gate 					if ((int32_t)u64_val >=
7470Sstevel@tonic-gate 					    (int32_t)(ep->e_value.num))
7480Sstevel@tonic-gate 						continue;
7490Sstevel@tonic-gate 					break;
7500Sstevel@tonic-gate 				}
7510Sstevel@tonic-gate 				/*FALLTHROUGH*/
7520Sstevel@tonic-gate 			case ULONG:
7530Sstevel@tonic-gate 				if ((uint32_t)u64_val >=
7540Sstevel@tonic-gate 				    (uint32_t)(ep->e_value.num))
7550Sstevel@tonic-gate 					continue;
7560Sstevel@tonic-gate 				break;
7570Sstevel@tonic-gate 			case LLONG:
7580Sstevel@tonic-gate 				if (ep->e_mask == 0) {
7590Sstevel@tonic-gate 					if ((int64_t)u64_val >=
7600Sstevel@tonic-gate 					    (int64_t)(ep->e_value.num))
7610Sstevel@tonic-gate 						continue;
7620Sstevel@tonic-gate 					break;
7630Sstevel@tonic-gate 				}
7640Sstevel@tonic-gate 				/*FALLTHROUGH*/
7650Sstevel@tonic-gate 			case ULLONG:
7660Sstevel@tonic-gate 				if (u64_val >= ep->e_value.num)
7670Sstevel@tonic-gate 					continue;
7680Sstevel@tonic-gate 				break;
7690Sstevel@tonic-gate 			default:
7700Sstevel@tonic-gate 				continue;
7710Sstevel@tonic-gate 			}
7720Sstevel@tonic-gate 			break;
7730Sstevel@tonic-gate 		case AND:
7740Sstevel@tonic-gate 			switch (ep->e_type) {
7750Sstevel@tonic-gate 			case BYTE:
7760Sstevel@tonic-gate 			case UBYTE:
7770Sstevel@tonic-gate 				if (((uint8_t)u64_val &
7780Sstevel@tonic-gate 				    (uint8_t)(ep->e_value.num)) ==
7790Sstevel@tonic-gate 				    (uint8_t)(ep->e_value.num))
7800Sstevel@tonic-gate 					break;
7810Sstevel@tonic-gate 				continue;
7820Sstevel@tonic-gate 			case SHORT:
7830Sstevel@tonic-gate 			case USHORT:
7840Sstevel@tonic-gate 				if (((uint16_t)u64_val &
7850Sstevel@tonic-gate 				    (uint16_t)(ep->e_value.num)) ==
7860Sstevel@tonic-gate 				    (uint16_t)(ep->e_value.num))
7870Sstevel@tonic-gate 					break;
7880Sstevel@tonic-gate 				continue;
7890Sstevel@tonic-gate 			case LONG:
7900Sstevel@tonic-gate 			case ULONG:
7910Sstevel@tonic-gate 				if (((uint32_t)u64_val &
7920Sstevel@tonic-gate 				    (uint32_t)(ep->e_value.num)) ==
7930Sstevel@tonic-gate 				    (uint32_t)(ep->e_value.num))
7940Sstevel@tonic-gate 					break;
7950Sstevel@tonic-gate 				continue;
7960Sstevel@tonic-gate 			case LLONG:
7970Sstevel@tonic-gate 			case ULLONG:
7980Sstevel@tonic-gate 				if ((u64_val & ep->e_value.num) ==
7990Sstevel@tonic-gate 				    ep->e_value.num)
8000Sstevel@tonic-gate 					break;
8010Sstevel@tonic-gate 				continue;
8020Sstevel@tonic-gate 			default:
8030Sstevel@tonic-gate 				continue;
8040Sstevel@tonic-gate 			}
8050Sstevel@tonic-gate 			break;
8060Sstevel@tonic-gate 		case NSET:
8070Sstevel@tonic-gate 			switch (ep->e_type) {
8080Sstevel@tonic-gate 			case BYTE:
8090Sstevel@tonic-gate 			case UBYTE:
8100Sstevel@tonic-gate 				if (((uint8_t)u64_val &
8110Sstevel@tonic-gate 				    (uint8_t)(ep->e_value.num)) !=
8120Sstevel@tonic-gate 				    (uint8_t)(ep->e_value.num))
8130Sstevel@tonic-gate 					break;
8140Sstevel@tonic-gate 				continue;
8150Sstevel@tonic-gate 			case SHORT:
8160Sstevel@tonic-gate 			case USHORT:
8170Sstevel@tonic-gate 				if (((uint16_t)u64_val &
8180Sstevel@tonic-gate 				    (uint16_t)(ep->e_value.num)) !=
8190Sstevel@tonic-gate 				    (uint16_t)(ep->e_value.num))
8200Sstevel@tonic-gate 					break;
8210Sstevel@tonic-gate 				continue;
8220Sstevel@tonic-gate 			case LONG:
8230Sstevel@tonic-gate 			case ULONG:
8240Sstevel@tonic-gate 				if (((uint32_t)u64_val &
8250Sstevel@tonic-gate 				    (uint32_t)(ep->e_value.num)) !=
8260Sstevel@tonic-gate 				    (uint32_t)(ep->e_value.num))
8270Sstevel@tonic-gate 					break;
8280Sstevel@tonic-gate 				continue;
8290Sstevel@tonic-gate 			case LLONG:
8300Sstevel@tonic-gate 			case ULLONG:
8310Sstevel@tonic-gate 				if ((u64_val & ep->e_value.num) !=
8320Sstevel@tonic-gate 				    ep->e_value.num)
8330Sstevel@tonic-gate 					break;
8340Sstevel@tonic-gate 				continue;
8350Sstevel@tonic-gate 			default:
8360Sstevel@tonic-gate 				continue;
8370Sstevel@tonic-gate 			}
8380Sstevel@tonic-gate 			break;
8390Sstevel@tonic-gate 		case ANY:	/* matches anything */
8400Sstevel@tonic-gate 			break;
8410Sstevel@tonic-gate 		default:	/* shouldn't occur; ignore it */
8420Sstevel@tonic-gate 			continue;
8430Sstevel@tonic-gate 		}
8440Sstevel@tonic-gate 		if (lev1)
8450Sstevel@tonic-gate 			(void) putchar(' ');
8460Sstevel@tonic-gate 		if (ep->e_opcode & SUB) {
8470Sstevel@tonic-gate 			switch (ep->e_type) {
8480Sstevel@tonic-gate 			case LLONG:
8490Sstevel@tonic-gate #ifdef XPG4
8500Sstevel@tonic-gate 				if (ep->e_mask == 0) {
8510Sstevel@tonic-gate 					(void) printf(ep->e_str,
8520Sstevel@tonic-gate 						(int64_t)u64_val);
8530Sstevel@tonic-gate 					break;
8540Sstevel@tonic-gate 				}
8550Sstevel@tonic-gate #endif	/* XPG4 */
8560Sstevel@tonic-gate 				/*FALLTHROUGH*/
8570Sstevel@tonic-gate 			case ULLONG:
8580Sstevel@tonic-gate 				(void) printf(ep->e_str, u64_val);
8590Sstevel@tonic-gate 				break;
8600Sstevel@tonic-gate 			case LONG:
8610Sstevel@tonic-gate #ifdef XPG4
8620Sstevel@tonic-gate 				if (ep->e_mask == 0) {
8630Sstevel@tonic-gate 					(void) printf(ep->e_str,
8640Sstevel@tonic-gate 						(int32_t)u64_val);
8650Sstevel@tonic-gate 					break;
8660Sstevel@tonic-gate 				}
8670Sstevel@tonic-gate #endif	/* XPG4 */
8680Sstevel@tonic-gate 				/*FALLTHROUGH*/
8690Sstevel@tonic-gate 			case ULONG:
8700Sstevel@tonic-gate 				(void) printf(ep->e_str,
8710Sstevel@tonic-gate 				    (uint32_t)u64_val);
8720Sstevel@tonic-gate 				break;
8730Sstevel@tonic-gate 			case SHORT:
8740Sstevel@tonic-gate #ifdef XPG4
8750Sstevel@tonic-gate 				if (ep->e_mask == 0) {
8760Sstevel@tonic-gate 					(void) printf(ep->e_str,
8770Sstevel@tonic-gate 						(int16_t)u64_val);
8780Sstevel@tonic-gate 					break;
8790Sstevel@tonic-gate 				}
8800Sstevel@tonic-gate #endif	/* XPG4 */
8810Sstevel@tonic-gate 				/*FALLTHROUGH*/
8820Sstevel@tonic-gate 			case USHORT:
8830Sstevel@tonic-gate 				(void) printf(ep->e_str,
8840Sstevel@tonic-gate 				    (uint16_t)u64_val);
8850Sstevel@tonic-gate 				break;
8860Sstevel@tonic-gate 			case BYTE:
8870Sstevel@tonic-gate #ifdef XPG4
8880Sstevel@tonic-gate 				if (ep->e_mask == 0) {
8890Sstevel@tonic-gate 					(void) printf(ep->e_str,
8900Sstevel@tonic-gate 						(int8_t)u64_val);
8910Sstevel@tonic-gate 					break;
8920Sstevel@tonic-gate 				}
8930Sstevel@tonic-gate #endif	/* XPG4 */
8940Sstevel@tonic-gate 				/*FALLTHROUGH*/
8950Sstevel@tonic-gate 			case UBYTE:
8960Sstevel@tonic-gate 				(void) printf(ep->e_str,
8970Sstevel@tonic-gate 				    (uint8_t)u64_val);
8980Sstevel@tonic-gate 				break;
8990Sstevel@tonic-gate 			case STR:
9000Sstevel@tonic-gate 				/*
9010Sstevel@tonic-gate 				 * Note: Currently can't get type
9020Sstevel@tonic-gate 				 * STR here because we already
9030Sstevel@tonic-gate 				 * did a 'continue' out of the
9040Sstevel@tonic-gate 				 * loop earlier for case STR
9050Sstevel@tonic-gate 				 */
9060Sstevel@tonic-gate 				break;
9070Sstevel@tonic-gate 			}
9080Sstevel@tonic-gate 		} else
9090Sstevel@tonic-gate 			(void) printf(ep->e_str);
9100Sstevel@tonic-gate 		lev1 = 1;
9110Sstevel@tonic-gate 	}
9120Sstevel@tonic-gate 	result = lev1 ? (int)(1 + ep - mtab) : 0;
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	return (result);
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate static void
showstr(char * s,int width)9180Sstevel@tonic-gate showstr(char *s, int width)
9190Sstevel@tonic-gate {
9200Sstevel@tonic-gate 	char c;
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	while ((c = *s++) != '\0')
9230Sstevel@tonic-gate 		if (c >= 040 && c < 0176) {
9240Sstevel@tonic-gate 			(void) putchar(c);
9250Sstevel@tonic-gate 			width--;
9260Sstevel@tonic-gate 		} else {
9270Sstevel@tonic-gate 			(void) putchar('\\');
9280Sstevel@tonic-gate 			switch (c) {
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 			case '\n':
9310Sstevel@tonic-gate 				(void) putchar('n');
9320Sstevel@tonic-gate 				width -= 2;
9330Sstevel@tonic-gate 				break;
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 			case '\r':
9360Sstevel@tonic-gate 				(void) putchar('r');
9370Sstevel@tonic-gate 				width -= 2;
9380Sstevel@tonic-gate 				break;
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 			case '\a':
9410Sstevel@tonic-gate 				(void) putchar('a');
9420Sstevel@tonic-gate 				width -= 2;
9430Sstevel@tonic-gate 				break;
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 			case '\b':
9460Sstevel@tonic-gate 				(void) putchar('b');
9470Sstevel@tonic-gate 				width -= 2;
9480Sstevel@tonic-gate 				break;
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 			case '\t':
9510Sstevel@tonic-gate 				(void) putchar('t');
9520Sstevel@tonic-gate 				width -= 2;
9530Sstevel@tonic-gate 				break;
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 			case '\f':
9560Sstevel@tonic-gate 				(void) putchar('f');
9570Sstevel@tonic-gate 				width -= 2;
9580Sstevel@tonic-gate 				break;
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate 			case '\v':
9610Sstevel@tonic-gate 				(void) putchar('v');
9620Sstevel@tonic-gate 				width -= 2;
9630Sstevel@tonic-gate 				break;
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 			default:
9660Sstevel@tonic-gate 				(void) printf("%.3o", c & 0377);
9670Sstevel@tonic-gate 				width -= 4;
9680Sstevel@tonic-gate 				break;
9690Sstevel@tonic-gate 			}
9700Sstevel@tonic-gate 		}
9710Sstevel@tonic-gate 	while (width >= 0) {
9720Sstevel@tonic-gate 		(void) putchar(' ');
9730Sstevel@tonic-gate 		width--;
9740Sstevel@tonic-gate 	};
9750Sstevel@tonic-gate }
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate static char *
type_to_name(Entry * ep)9780Sstevel@tonic-gate type_to_name(Entry *ep)
9790Sstevel@tonic-gate {
9800Sstevel@tonic-gate 	static char buf[20];
9810Sstevel@tonic-gate 	char	*s;
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	switch (ep->e_type) {
9840Sstevel@tonic-gate 	case BYTE:
9850Sstevel@tonic-gate 		s = "byte";
9860Sstevel@tonic-gate 		break;
9870Sstevel@tonic-gate 	case SHORT:
9880Sstevel@tonic-gate 		s = "short";
9890Sstevel@tonic-gate 		break;
9900Sstevel@tonic-gate 	case LONG:
9910Sstevel@tonic-gate 		s = "long";
9920Sstevel@tonic-gate 		break;
9930Sstevel@tonic-gate 	case LLONG:
9940Sstevel@tonic-gate 		s = "llong";
9950Sstevel@tonic-gate 		break;
9960Sstevel@tonic-gate 	case UBYTE:
9970Sstevel@tonic-gate 		s = "ubyte";
9980Sstevel@tonic-gate 		break;
9990Sstevel@tonic-gate 	case USHORT:
10000Sstevel@tonic-gate 		s = "ushort";
10010Sstevel@tonic-gate 		break;
10020Sstevel@tonic-gate 	case ULONG:
10030Sstevel@tonic-gate 		s = "ulong";
10040Sstevel@tonic-gate 		break;
10050Sstevel@tonic-gate 	case ULLONG:
10060Sstevel@tonic-gate 		s = "ullong";
10070Sstevel@tonic-gate 		break;
10080Sstevel@tonic-gate 	case STR:
10090Sstevel@tonic-gate 		return ("string");
10100Sstevel@tonic-gate 	default:
10110Sstevel@tonic-gate 		/* more of an emergency measure .. */
10120Sstevel@tonic-gate 		(void) sprintf(buf, "%d", ep->e_type);
10130Sstevel@tonic-gate 		return (buf);
10140Sstevel@tonic-gate 	}
10150Sstevel@tonic-gate 	if (ep->e_mask) {
10160Sstevel@tonic-gate 		(void) snprintf(buf, sizeof (buf), "%s&0x%llx", s, ep->e_mask);
10170Sstevel@tonic-gate 		return (buf);
10180Sstevel@tonic-gate 	} else
10190Sstevel@tonic-gate 		return (s);
10200Sstevel@tonic-gate }
10210Sstevel@tonic-gate 
10220Sstevel@tonic-gate static char
op_to_name(char op)10230Sstevel@tonic-gate op_to_name(char op)
10240Sstevel@tonic-gate {
10250Sstevel@tonic-gate 	char c;
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 	switch (op & ~SUB) {
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 	case EQ:
10300Sstevel@tonic-gate 	case STRC:
10310Sstevel@tonic-gate 		c = '=';
10320Sstevel@tonic-gate 		break;
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	case GT:
10350Sstevel@tonic-gate 		c = '>';
10360Sstevel@tonic-gate 		break;
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 	case LT:
10390Sstevel@tonic-gate 		c = '<';
10400Sstevel@tonic-gate 		break;
10410Sstevel@tonic-gate 
10420Sstevel@tonic-gate 	case ANY:
10430Sstevel@tonic-gate 		c = 'x';
10440Sstevel@tonic-gate 		break;
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	case AND:
10470Sstevel@tonic-gate 		c = '&';
10480Sstevel@tonic-gate 		break;
10490Sstevel@tonic-gate 
10500Sstevel@tonic-gate 	case NSET:
10510Sstevel@tonic-gate 		c = '^';
10520Sstevel@tonic-gate 		break;
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	default:
10550Sstevel@tonic-gate 		c = '?';
10560Sstevel@tonic-gate 		break;
10570Sstevel@tonic-gate 	}
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate 	return (c);
10600Sstevel@tonic-gate }
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate /*
10630Sstevel@tonic-gate  * f_prtmtab - Prints out a header, then entries from both magic
10640Sstevel@tonic-gate  *	tables, mtab1 and mtab2, if any exist.
10650Sstevel@tonic-gate  */
10660Sstevel@tonic-gate void
f_prtmtab(void)10670Sstevel@tonic-gate f_prtmtab(void)
10680Sstevel@tonic-gate {
10690Sstevel@tonic-gate 	Entry	*mtab;
10700Sstevel@tonic-gate 	Entry	*ep;
10710Sstevel@tonic-gate 	int	count;
10720Sstevel@tonic-gate 
10730Sstevel@tonic-gate 	(void) printf("%-7s %-7s %-10s %-7s %-11s %s\n",
10740Sstevel@tonic-gate 		"level", "off", "type", "opcode", "value", "string");
10750Sstevel@tonic-gate 	for (mtab = mtab1, count = 1; count <= 2; count++, mtab = mtab2) {
10760Sstevel@tonic-gate 		if (mtab == (Entry *)NULL) {
10770Sstevel@tonic-gate 			continue;
10780Sstevel@tonic-gate 		}
10790Sstevel@tonic-gate 		for (ep = mtab; ep->e_off != -1L; ep++) {
10800Sstevel@tonic-gate 			(void) printf("%-7d %-7ld %-10s %-7c ",
10810Sstevel@tonic-gate 			    ep->e_level,
10820Sstevel@tonic-gate 			    ep->e_off, type_to_name(ep),
10830Sstevel@tonic-gate 			    op_to_name(ep->e_opcode));
10840Sstevel@tonic-gate 			if (ep->e_type == STR) {
10850Sstevel@tonic-gate 				showstr(ep->e_value.str, 10);
10860Sstevel@tonic-gate 			} else {	/* numeric */
10870Sstevel@tonic-gate 				(void) printf("%-#11llo", ep->e_value.num);
10880Sstevel@tonic-gate 			}
10890Sstevel@tonic-gate 			(void) printf(" %s", ep->e_str);
10900Sstevel@tonic-gate 			if (ep->e_opcode & SUB)
10910Sstevel@tonic-gate 				(void) printf("\tsubst");
10920Sstevel@tonic-gate 			(void) printf("\n");
10930Sstevel@tonic-gate 		}
10940Sstevel@tonic-gate 	}
10950Sstevel@tonic-gate }
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate intmax_t
f_getmaxoffset(int first)10980Sstevel@tonic-gate f_getmaxoffset(int first)
10990Sstevel@tonic-gate {
11000Sstevel@tonic-gate 	Entry *mtab;
11010Sstevel@tonic-gate 	Entry *ep;
11020Sstevel@tonic-gate 	intmax_t cur;
11030Sstevel@tonic-gate 	intmax_t max = 0;
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	if (first) {
11060Sstevel@tonic-gate 		mtab = mtab1;
11070Sstevel@tonic-gate 	} else {
11080Sstevel@tonic-gate 		mtab = mtab2;
11090Sstevel@tonic-gate 	}
11100Sstevel@tonic-gate 	if (mtab == (Entry *)NULL) {
11110Sstevel@tonic-gate 		return (0);
11120Sstevel@tonic-gate 	}
11130Sstevel@tonic-gate 	for (ep = mtab; ep->e_off != -1L; ep++) {
11140Sstevel@tonic-gate 		cur = ep->e_off;
11150Sstevel@tonic-gate 		switch (ep->e_type) {
11160Sstevel@tonic-gate 		case STR:
11170Sstevel@tonic-gate 			cur += strlen(ep->e_value.str);
11180Sstevel@tonic-gate 			break;
11190Sstevel@tonic-gate 		case BYTE:
11200Sstevel@tonic-gate 		case UBYTE:
11210Sstevel@tonic-gate 			cur += sizeof (uchar_t);
11220Sstevel@tonic-gate 			break;
11230Sstevel@tonic-gate 		case SHORT:
11240Sstevel@tonic-gate 		case USHORT:
11250Sstevel@tonic-gate 			cur += sizeof (uint16_t);
11260Sstevel@tonic-gate 			break;
11270Sstevel@tonic-gate 		case LONG:
11280Sstevel@tonic-gate 		case ULONG:
11290Sstevel@tonic-gate 			cur += sizeof (uint32_t);
11300Sstevel@tonic-gate 			break;
11310Sstevel@tonic-gate 		case LLONG:
11320Sstevel@tonic-gate 		case ULLONG:
11330Sstevel@tonic-gate 			cur += sizeof (uint64_t);
11340Sstevel@tonic-gate 			break;
11350Sstevel@tonic-gate 		}
11360Sstevel@tonic-gate 		if (cur <= INT_MAX && cur > max) {
11370Sstevel@tonic-gate 			max = cur;
11380Sstevel@tonic-gate 		}
11390Sstevel@tonic-gate 	}
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	return (max);
11420Sstevel@tonic-gate }
1143