xref: /illumos-gate/usr/src/cmd/file/magicutils.c (revision e75b2cb0)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved	*/
28 
29 /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
30 /*	  All Rights Reserved	*/
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <inttypes.h>
39 #include <sys/types.h>
40 #include <libintl.h>
41 
42 /*
43  *	Types
44  */
45 
46 #define	BYTE	1
47 #define	SHORT	2
48 #define	LONG	4
49 #define	LLONG	8
50 #define	UBYTE	16
51 #define	USHORT	32
52 #define	ULONG	64
53 #define	ULLONG	128
54 #define	STR	256
55 
56 /*
57  *	Opcodes
58  */
59 
60 #define	EQ	0
61 #define	GT	1
62 #define	LT	2
63 #define	STRC	3	/* string compare */
64 #define	ANY	4
65 #define	AND	5
66 #define	NSET	6	/* True if bit is not set */
67 #define	SUB	64	/* or'ed in, SUBstitution string, for example */
68 			/* %ld, %s, %lo mask: with bit 6 on, used to locate */
69 			/* print formats */
70 /*
71  *	Misc
72  */
73 
74 #define	BSZ	128
75 #define	NENT	200
76 
77 /*
78  *	Structure of magic file entry
79  */
80 
81 struct	entry	{
82 	char		e_level;	/* 0 or 1 */
83 	off_t		e_off;		/* in bytes */
84 	uint32_t	e_type;		/* BYTE, SHORT, STR, et al */
85 	char		e_opcode;	/* EQ, GT, LT, ANY, AND, NSET */
86 	uint64_t	e_mask;		/* if non-zero, mask value with this */
87 	union	{
88 		uint64_t	num;
89 		char		*str;
90 	}	e_value;
91 	const char	*e_str;
92 };
93 
94 /* Non-localized string giving name of command.  Defined in file.c */
95 extern const char	*File;
96 
97 typedef	struct entry	Entry;
98 
99 static Entry	*mtab1;	/* 1st magic table, applied before default tests */
100 
101 	/*
102 	 * 2nd magic table, includes default tests and magic entries
103 	 * to be applied after default position-sensitive tests
104 	 */
105 static Entry	*mtab2;
106 
107 static Entry	*mend1;	/* one past last-allocated entry in mtab1 */
108 static Entry	*mend2;	/* one past last-allocated entry in mtab2 */
109 
110 static Entry	*ep1;	/* current entry in mtab1 */
111 static Entry	*ep2;	/* current entry in mtab2 */
112 
113 static char *
114 getstr(char *p, char *file)
115 {
116 	char	*newstr;
117 	char	*s;
118 	long	val;
119 	int	base;
120 
121 	newstr = (char *)malloc((strlen(p) + 1) * sizeof (char));
122 	if (newstr == NULL) {
123 		int err = errno;
124 		(void) fprintf(stderr, gettext("%s: malloc failed: %s\n"),
125 		    File, strerror(err));
126 		return (NULL);
127 	}
128 
129 	s = newstr;
130 	while (*p != '\0') {
131 		if (*p != '\\') {
132 			*s++ = *p++;
133 			continue;
134 		}
135 		p++;
136 		if (*p == '\0')
137 			break;
138 		if (isdigit(*p)) {
139 			if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) {
140 				/* hex */
141 				base = 16;
142 			} else {
143 				base = 8;
144 			}
145 			errno = 0;
146 			val = strtol(p, &p, base);
147 			if (val > UCHAR_MAX || val < 0 || errno != 0) {
148 				(void) fprintf(stderr, gettext("%s: %s: magic "
149 				    "table invalid string value\n"), File,
150 				    file);
151 				return (NULL);
152 			}
153 			*s++ = (char)val;
154 		} else {
155 			/* escape the character */
156 			switch (*p) {
157 			case 'n':
158 				*s = '\n';
159 				break;
160 			case 'r':
161 				*s = '\r';
162 				break;
163 			case 'a':
164 				*s = '\a';
165 				break;
166 			case 'b':
167 				*s = '\b';
168 				break;
169 			case 'f':
170 				*s = '\f';
171 				break;
172 			case 't':
173 				*s = '\t';
174 				break;
175 			case 'v':
176 				*s = '\v';
177 				break;
178 			default:
179 				*s = *p;
180 				break;
181 			}
182 			p++;
183 			s++;
184 		}
185 	}
186 	*s = '\0';
187 	return (newstr);
188 }
189 
190 /*
191  * f_mkmtab - fills mtab array of magic table entries with
192  *	values from the file magfile.
193  *	May be called more than once if multiple magic
194  *	files were specified.
195  *	Stores entries sequentially in one of two magic
196  *	tables: mtab1, if first = 1; mtab2 otherwise.
197  *
198  *	If -c option is specified, cflg is non-zero, and
199  *	f_mkmtab() reports on errors in the magic file.
200  *
201  *	Two magic tables may need to be created.  The first
202  *	one (mtab1) contains magic entries to be checked before
203  *	the programmatic default position-sensitive tests in
204  *	def_position_tests().
205  *	The second one (mtab2) should start with the default
206  *	/etc/magic file entries and is to be checked after
207  *	the programmatic default position-sensitive tests in
208  *	def_position_tests().  The parameter "first" would
209  *	be 1 for the former set of tables, 0 for the latter
210  *	set of magic tables.
211  *	No mtab2 should be created if file will not be
212  *	applying default tests; in that case, all magic table
213  *	entries should be in mtab1.
214  *
215  *	f_mkmtab returns 0 on success, -1 on error.  The calling
216  *	program is not expected to proceed after f_mkmtab()
217  *	returns an error.
218  */
219 
220 int
221 f_mkmtab(char *magfile, int cflg, int first)
222 {
223 	Entry	*mtab;	/* generic magic table pointer */
224 	Entry	*ep;	/* current magic table entry */
225 	Entry	*mend;	/* one past last-allocated entry of mtab */
226 	FILE	*fp;
227 	int	lcnt = 0;
228 	char	buf[BSZ];
229 	size_t	tbsize;
230 	size_t	oldsize;
231 
232 	if (first) {
233 		mtab = mtab1;
234 		mend = mend1;
235 		ep = ep1;
236 	} else {
237 		mtab = mtab2;
238 		mend = mend2;
239 		ep = ep2;
240 	}
241 
242 	/* mtab may have been allocated on a previous f_mkmtab call */
243 	if (mtab == (Entry *)NULL) {
244 		if ((mtab = calloc(NENT, sizeof (Entry))) == NULL) {
245 			int err = errno;
246 			(void) fprintf(stderr, gettext("%s: malloc "
247 			    "failed: %s\n"), File, strerror(err));
248 			return (-1);
249 		}
250 
251 		ep = mtab;
252 		mend = &mtab[NENT];
253 	}
254 
255 	errno = 0;
256 	if ((fp = fopen(magfile, "r")) == NULL) {
257 		int err = errno;
258 		(void) fprintf(stderr, gettext("%s: %s: cannot open magic "
259 		    "file: %s\n"), File, magfile, err ? strerror(err) : "");
260 		return (-1);
261 	}
262 	while (fgets(buf, BSZ, fp) != NULL) {
263 		char	*p = buf;
264 		char	*p2;
265 		char	*p3;
266 		char	opc;
267 
268 		/*
269 		 * ensure we have one extra entry allocated
270 		 * to mark end of the table, after the while loop
271 		 */
272 		if (ep >= (mend - 1)) {
273 			oldsize = mend - mtab;
274 			tbsize = (NENT + oldsize) * sizeof (Entry);
275 			if ((mtab = realloc(mtab, tbsize)) == NULL) {
276 				int err = errno;
277 				(void) fprintf(stderr, gettext("%s: malloc "
278 				    "failed: %s\n"), File, strerror(err));
279 				return (-1);
280 			} else {
281 				(void) memset(mtab + oldsize, 0,
282 				    sizeof (Entry) * NENT);
283 				mend = &mtab[tbsize / sizeof (Entry)];
284 				ep = &mtab[oldsize-1];
285 			}
286 		}
287 
288 		lcnt++;
289 		if (*p == '\n' || *p == '#')
290 			continue;
291 
292 
293 			/* LEVEL */
294 		if (*p == '>') {
295 			ep->e_level = 1;
296 			p++;
297 		}
298 			/* OFFSET */
299 		p2 = strchr(p, '\t');
300 		if (p2 == NULL) {
301 			if (cflg)
302 				(void) fprintf(stderr, gettext("%s: %s: format "
303 				    "error, no tab after %s on line %d\n"),
304 				    File, magfile, p, lcnt);
305 			continue;
306 		}
307 		*p2++ = '\0';
308 		ep->e_off = strtol((const char *)p, (char **)NULL, 0);
309 		while (*p2 == '\t')
310 			p2++;
311 			/* TYPE */
312 		p = p2;
313 		p2 = strchr(p, '\t');
314 		if (p2 == NULL) {
315 			if (cflg)
316 				(void) fprintf(stderr, gettext("%s: %s: format "
317 				    "error, no tab after %s on line %d\n"),
318 				    File, magfile, p, lcnt);
319 			continue;
320 		}
321 		*p2++ = '\0';
322 		p3 = strchr(p, '&');
323 		if (p3 != NULL) {
324 			*p3++ = '\0';
325 			ep->e_mask = strtoull((const char *)p3, (char **)NULL,
326 			    0);	/* returns 0 or ULLONG_MAX on error */
327 		} else {
328 			ep->e_mask = 0ULL;
329 		}
330 		switch (*p) {
331 			case 'd':
332 				if (*(p+1) == '\0') {
333 					/* d */
334 					ep->e_type = LONG;
335 				} else if (*(p+2) == '\0') {	/* d? */
336 					switch (*(p+1)) {
337 						case 'C':
338 						case '1':
339 							/* dC, d1 */
340 							ep->e_type = BYTE;
341 							break;
342 						case 'S':
343 						case '2':
344 							/* dS, d2 */
345 							ep->e_type = SHORT;
346 							break;
347 						case 'I':
348 						case 'L':
349 						case '4':
350 							/* dI, dL, d4 */
351 							ep->e_type = LONG;
352 							break;
353 						case '8':
354 							/* d8 */
355 							ep->e_type = LLONG;
356 							break;
357 						default:
358 							ep->e_type = LONG;
359 							break;
360 					}
361 				}
362 				break;
363 			case 'l':
364 				if (*(p+1) == 'l') {	/* llong */
365 					ep->e_type = LLONG;
366 				} else {		/* long */
367 					ep->e_type = LONG;
368 				}
369 				break;
370 			case 's':
371 				if (*(p+1) == 'h') {
372 					/* short */
373 					ep->e_type = SHORT;
374 				} else {
375 					/* s or string */
376 					ep->e_type = STR;
377 				}
378 				break;
379 			case 'u':
380 				if (*(p+1) == '\0') {
381 					/* u */
382 					ep->e_type = ULONG;
383 				} else if (*(p+2) == '\0') {	/* u? */
384 					switch (*(p+1)) {
385 						case 'C':
386 						case '1':
387 							/* uC, u1 */
388 							ep->e_type = UBYTE;
389 							break;
390 						case 'S':
391 						case '2':
392 							/* uS, u2 */
393 							ep->e_type = USHORT;
394 							break;
395 						case 'I':
396 						case 'L':
397 						case '4':
398 							/* uI, uL, u4 */
399 							ep->e_type = ULONG;
400 							break;
401 						case '8':
402 							/* u8 */
403 							ep->e_type = ULLONG;
404 							break;
405 						default:
406 							ep->e_type = ULONG;
407 							break;
408 					}
409 				} else { /* u?* */
410 					switch (*(p+1)) {
411 					case 'b':	/* ubyte */
412 						ep->e_type = UBYTE;
413 						break;
414 					case 's':	/* ushort */
415 						ep->e_type = USHORT;
416 						break;
417 					case 'l':
418 						if (*(p+2) == 'l') {
419 							/* ullong */
420 							ep->e_type = ULLONG;
421 						} else {
422 							/* ulong */
423 							ep->e_type = ULONG;
424 						}
425 						break;
426 					default:
427 						/* default, same as "u" */
428 						ep->e_type = ULONG;
429 						break;
430 					}
431 				}
432 				break;
433 			default:
434 				/* retain (undocumented) default type */
435 				ep->e_type = BYTE;
436 				break;
437 		}
438 		if (ep->e_type == 0) {
439 			ep->e_type = BYTE;	/* default */
440 		}
441 		while (*p2 == '\t')
442 			p2++;
443 			/* OP-VALUE */
444 		p = p2;
445 		p2 = strchr(p, '\t');
446 		if (p2 == NULL) {
447 			if (cflg)
448 				(void) fprintf(stderr, gettext("%s: %s: format "
449 				    "error, no tab after %s on line %d\n"),
450 				    File, magfile, p, lcnt);
451 			continue;
452 		}
453 		*p2++ = '\0';
454 		if (ep->e_type != STR) {
455 			opc = *p++;
456 			switch (opc) {
457 			case '=':
458 				ep->e_opcode = EQ;
459 				break;
460 
461 			case '>':
462 				ep->e_opcode = GT;
463 				break;
464 
465 			case '<':
466 				ep->e_opcode = LT;
467 				break;
468 
469 			case 'x':
470 				ep->e_opcode = ANY;
471 				break;
472 
473 			case '&':
474 				ep->e_opcode = AND;
475 				break;
476 
477 			case '^':
478 				ep->e_opcode = NSET;
479 				break;
480 			default:	/* EQ (i.e. 0) is default	*/
481 				p--;	/* since global ep->e_opcode=0	*/
482 			}
483 		}
484 		if (ep->e_opcode != ANY) {
485 			if (ep->e_type != STR) {
486 				ep->e_value.num = strtoull((const char *)p,
487 				    (char **)NULL, 0);
488 			} else if ((ep->e_value.str =
489 			    getstr(p, magfile)) == NULL) {
490 				return (-1);
491 			}
492 		}
493 		p2 += strspn(p2, "\t");
494 			/* STRING */
495 		if ((ep->e_str = strdup(p2)) == NULL) {
496 			int err = errno;
497 			(void) fprintf(stderr, gettext("%s: malloc "
498 			    "failed: %s\n"), File, strerror(err));
499 			return (-1);
500 		} else {
501 			if ((p = strchr(ep->e_str, '\n')) != NULL)
502 				*p = '\0';
503 			if (strchr(ep->e_str, '%') != NULL)
504 				ep->e_opcode |= SUB;
505 		}
506 		ep++;
507 	}	/* end while (fgets) */
508 
509 	ep->e_off = -1L;	/* mark end of table */
510 	if (first) {
511 		mtab1 = mtab;
512 		mend1 = mend;
513 		ep1 = ep;
514 	} else {
515 		mtab2 = mtab;
516 		mend2 = mend;
517 		ep2 = ep;
518 	}
519 	if (fclose(fp) != 0) {
520 		int err = errno;
521 		(void) fprintf(stderr, gettext("%s: fclose failed: %s\n"),
522 		    File, strerror(err));
523 		return (-1);
524 	}
525 	return (0);
526 }
527 
528 /*
529  * Check for Magic Table entries in the file.
530  *
531  * Since there may be two sets of magic tables, first = 1
532  * for the first magic table (mtab1) and 0 for the second magic
533  * table (mtab2).
534  */
535 int
536 f_ckmtab(char *buf, int bufsize, int first)
537 {
538 	int		result;
539 	Entry		*mtab;
540 	Entry		*ep;
541 	char		*p;
542 	int		lev1 = 0;
543 
544 	uint16_t	u16_val;
545 	uint32_t	u32_val;
546 	uint64_t	u64_val;
547 
548 	if (first) {
549 		mtab = mtab1;
550 	} else {
551 		mtab = mtab2;
552 	}
553 
554 	if (mtab == (Entry *)NULL) {
555 		return (0);	/* no magic file tests in this table */
556 	}
557 
558 	for (ep = mtab; ep->e_off != -1L; ep++) {  /* -1 offset marks end of */
559 		if (lev1) {			/* valid magic file entries */
560 			if (ep->e_level != 1)
561 				break;
562 		} else if (ep->e_level == 1) {
563 			continue;
564 		}
565 		if (ep->e_off > (off_t)bufsize)
566 			continue;
567 		p = &buf[ep->e_off];
568 		switch (ep->e_type) {
569 		case STR:
570 		{
571 			if (strncmp(p, ep->e_value.str,
572 			    strlen(ep->e_value.str)))
573 				continue;
574 			if (lev1) {
575 				(void) putchar(' ');
576 			}
577 			if (ep->e_opcode & SUB)
578 				(void) printf(ep->e_str,
579 				    ep->e_value.str);
580 			else
581 				(void) printf(ep->e_str);
582 			lev1 = 1;
583 			continue;
584 			/*
585 			 * We've matched the string and printed the message;
586 			 * no STR processing occurs beyond this point.
587 			 */
588 		}
589 
590 		case BYTE:
591 		case UBYTE:
592 			u64_val = (uint64_t)(uint8_t)(*p);
593 			break;
594 
595 		case SHORT:
596 		case USHORT:
597 			(void) memcpy(&u16_val, p, sizeof (uint16_t));
598 			u64_val = (uint64_t)u16_val;
599 			break;
600 
601 		case LONG:
602 		case ULONG:
603 			(void) memcpy(&u32_val, p, sizeof (uint32_t));
604 			u64_val = (uint64_t)u32_val;
605 			break;
606 
607 		case LLONG:
608 		case ULLONG:
609 			(void) memcpy(&(u64_val), p, sizeof (uint64_t));
610 			break;
611 
612 		}
613 
614 		if (ep->e_mask) {
615 			u64_val &= ep->e_mask;
616 		}
617 
618 		/*
619 		 * Compare the values according to the size and sign
620 		 * of the type.  For =, &, and ^ operators, the sign
621 		 * does not have any effect, so these are always compared
622 		 * unsigned.  Only for < and > operators is the
623 		 * sign significant.
624 		 * If the file value was masked, the compare should
625 		 * be unsigned.
626 		 */
627 		switch (ep->e_opcode & ~SUB) {
628 		case EQ:
629 			switch (ep->e_type) {
630 			case BYTE:
631 			case UBYTE:
632 				if ((uint8_t)u64_val !=
633 				    (uint8_t)(ep->e_value.num))
634 					continue;
635 				break;
636 			case SHORT:
637 			case USHORT:
638 				if ((uint16_t)u64_val !=
639 				    (uint16_t)(ep->e_value.num))
640 					continue;
641 				break;
642 			case LONG:
643 			case ULONG:
644 				if ((uint32_t)u64_val !=
645 				    (uint32_t)(ep->e_value.num))
646 					continue;
647 				break;
648 			case LLONG:
649 			case ULLONG:
650 				if (u64_val != ep->e_value.num)
651 					continue;
652 				break;
653 			default:
654 				continue;
655 			}
656 			break;
657 		case GT:
658 			switch (ep->e_type) {
659 			case BYTE:
660 				if (ep->e_mask == 0) {
661 					if ((int8_t)u64_val <=
662 					    (int8_t)(ep->e_value.num))
663 						continue;
664 					break;
665 				}
666 				/*FALLTHROUGH*/
667 			case UBYTE:
668 				if ((uint8_t)u64_val <=
669 				    (uint8_t)(ep->e_value.num))
670 					continue;
671 				break;
672 			case SHORT:
673 				if (ep->e_mask == 0) {
674 					if ((int16_t)u64_val <=
675 					    (int16_t)(ep->e_value.num))
676 						continue;
677 					break;
678 				}
679 				/*FALLTHROUGH*/
680 			case USHORT:
681 				if ((uint16_t)u64_val <=
682 				    (uint16_t)(ep->e_value.num))
683 					continue;
684 				break;
685 			case LONG:
686 				if (ep->e_mask == 0) {
687 					if ((int32_t)u64_val <=
688 					    (int32_t)(ep->e_value.num))
689 						continue;
690 					break;
691 				}
692 				/*FALLTHROUGH*/
693 			case ULONG:
694 				if ((uint32_t)u64_val <=
695 				    (uint32_t)(ep->e_value.num))
696 					continue;
697 				break;
698 			case LLONG:
699 				if (ep->e_mask == 0) {
700 					if ((int64_t)u64_val <=
701 					    (int64_t)(ep->e_value.num))
702 						continue;
703 					break;
704 				}
705 				/*FALLTHROUGH*/
706 			case ULLONG:
707 				if (u64_val <= ep->e_value.num)
708 					continue;
709 				break;
710 			default:
711 				continue;
712 			}
713 			break;
714 		case LT:
715 			switch (ep->e_type) {
716 			case BYTE:
717 				if (ep->e_mask == 0) {
718 					if ((int8_t)u64_val >=
719 					    (int8_t)(ep->e_value.num))
720 						continue;
721 					break;
722 				}
723 				/*FALLTHROUGH*/
724 			case UBYTE:
725 				if ((uint8_t)u64_val >=
726 				    (uint8_t)(ep->e_value.num))
727 					continue;
728 				break;
729 			case SHORT:
730 				if (ep->e_mask == 0) {
731 					if ((int16_t)u64_val >=
732 					    (int16_t)(ep->e_value.num))
733 						continue;
734 					break;
735 				}
736 				/*FALLTHROUGH*/
737 			case USHORT:
738 				if ((uint16_t)u64_val >=
739 				    (uint16_t)(ep->e_value.num))
740 					continue;
741 				break;
742 			case LONG:
743 				if (ep->e_mask == 0) {
744 					if ((int32_t)u64_val >=
745 					    (int32_t)(ep->e_value.num))
746 						continue;
747 					break;
748 				}
749 				/*FALLTHROUGH*/
750 			case ULONG:
751 				if ((uint32_t)u64_val >=
752 				    (uint32_t)(ep->e_value.num))
753 					continue;
754 				break;
755 			case LLONG:
756 				if (ep->e_mask == 0) {
757 					if ((int64_t)u64_val >=
758 					    (int64_t)(ep->e_value.num))
759 						continue;
760 					break;
761 				}
762 				/*FALLTHROUGH*/
763 			case ULLONG:
764 				if (u64_val >= ep->e_value.num)
765 					continue;
766 				break;
767 			default:
768 				continue;
769 			}
770 			break;
771 		case AND:
772 			switch (ep->e_type) {
773 			case BYTE:
774 			case UBYTE:
775 				if (((uint8_t)u64_val &
776 				    (uint8_t)(ep->e_value.num)) ==
777 				    (uint8_t)(ep->e_value.num))
778 					break;
779 				continue;
780 			case SHORT:
781 			case USHORT:
782 				if (((uint16_t)u64_val &
783 				    (uint16_t)(ep->e_value.num)) ==
784 				    (uint16_t)(ep->e_value.num))
785 					break;
786 				continue;
787 			case LONG:
788 			case ULONG:
789 				if (((uint32_t)u64_val &
790 				    (uint32_t)(ep->e_value.num)) ==
791 				    (uint32_t)(ep->e_value.num))
792 					break;
793 				continue;
794 			case LLONG:
795 			case ULLONG:
796 				if ((u64_val & ep->e_value.num) ==
797 				    ep->e_value.num)
798 					break;
799 				continue;
800 			default:
801 				continue;
802 			}
803 			break;
804 		case NSET:
805 			switch (ep->e_type) {
806 			case BYTE:
807 			case UBYTE:
808 				if (((uint8_t)u64_val &
809 				    (uint8_t)(ep->e_value.num)) !=
810 				    (uint8_t)(ep->e_value.num))
811 					break;
812 				continue;
813 			case SHORT:
814 			case USHORT:
815 				if (((uint16_t)u64_val &
816 				    (uint16_t)(ep->e_value.num)) !=
817 				    (uint16_t)(ep->e_value.num))
818 					break;
819 				continue;
820 			case LONG:
821 			case ULONG:
822 				if (((uint32_t)u64_val &
823 				    (uint32_t)(ep->e_value.num)) !=
824 				    (uint32_t)(ep->e_value.num))
825 					break;
826 				continue;
827 			case LLONG:
828 			case ULLONG:
829 				if ((u64_val & ep->e_value.num) !=
830 				    ep->e_value.num)
831 					break;
832 				continue;
833 			default:
834 				continue;
835 			}
836 			break;
837 		case ANY:	/* matches anything */
838 			break;
839 		default:	/* shouldn't occur; ignore it */
840 			continue;
841 		}
842 		if (lev1)
843 			(void) putchar(' ');
844 		if (ep->e_opcode & SUB) {
845 			switch (ep->e_type) {
846 			case LLONG:
847 #ifdef XPG4
848 				if (ep->e_mask == 0) {
849 					(void) printf(ep->e_str,
850 					    (int64_t)u64_val);
851 					break;
852 				}
853 #endif	/* XPG4 */
854 				/*FALLTHROUGH*/
855 			case ULLONG:
856 				(void) printf(ep->e_str, u64_val);
857 				break;
858 			case LONG:
859 #ifdef XPG4
860 				if (ep->e_mask == 0) {
861 					(void) printf(ep->e_str,
862 					    (int32_t)u64_val);
863 					break;
864 				}
865 #endif	/* XPG4 */
866 				/*FALLTHROUGH*/
867 			case ULONG:
868 				(void) printf(ep->e_str,
869 				    (uint32_t)u64_val);
870 				break;
871 			case SHORT:
872 #ifdef XPG4
873 				if (ep->e_mask == 0) {
874 					(void) printf(ep->e_str,
875 					    (int16_t)u64_val);
876 					break;
877 				}
878 #endif	/* XPG4 */
879 				/*FALLTHROUGH*/
880 			case USHORT:
881 				(void) printf(ep->e_str,
882 				    (uint16_t)u64_val);
883 				break;
884 			case BYTE:
885 #ifdef XPG4
886 				if (ep->e_mask == 0) {
887 					(void) printf(ep->e_str,
888 					    (int8_t)u64_val);
889 					break;
890 				}
891 #endif	/* XPG4 */
892 				/*FALLTHROUGH*/
893 			case UBYTE:
894 				(void) printf(ep->e_str,
895 				    (uint8_t)u64_val);
896 				break;
897 			case STR:
898 				/*
899 				 * Note: Currently can't get type
900 				 * STR here because we already
901 				 * did a 'continue' out of the
902 				 * loop earlier for case STR
903 				 */
904 				break;
905 			}
906 		} else
907 			(void) printf(ep->e_str);
908 		lev1 = 1;
909 	}
910 	result = lev1 ? (int)(1 + ep - mtab) : 0;
911 
912 	return (result);
913 }
914 
915 static void
916 showstr(char *s, int width)
917 {
918 	char c;
919 
920 	while ((c = *s++) != '\0')
921 		if (c >= 040 && c < 0176) {
922 			(void) putchar(c);
923 			width--;
924 		} else {
925 			(void) putchar('\\');
926 			switch (c) {
927 
928 			case '\n':
929 				(void) putchar('n');
930 				width -= 2;
931 				break;
932 
933 			case '\r':
934 				(void) putchar('r');
935 				width -= 2;
936 				break;
937 
938 			case '\a':
939 				(void) putchar('a');
940 				width -= 2;
941 				break;
942 
943 			case '\b':
944 				(void) putchar('b');
945 				width -= 2;
946 				break;
947 
948 			case '\t':
949 				(void) putchar('t');
950 				width -= 2;
951 				break;
952 
953 			case '\f':
954 				(void) putchar('f');
955 				width -= 2;
956 				break;
957 
958 			case '\v':
959 				(void) putchar('v');
960 				width -= 2;
961 				break;
962 
963 			default:
964 				(void) printf("%.3o", c & 0377);
965 				width -= 4;
966 				break;
967 			}
968 		}
969 	while (width >= 0) {
970 		(void) putchar(' ');
971 		width--;
972 	};
973 }
974 
975 static char *
976 type_to_name(Entry *ep)
977 {
978 	static char buf[20];
979 	char	*s;
980 
981 	switch (ep->e_type) {
982 	case BYTE:
983 		s = "byte";
984 		break;
985 	case SHORT:
986 		s = "short";
987 		break;
988 	case LONG:
989 		s = "long";
990 		break;
991 	case LLONG:
992 		s = "llong";
993 		break;
994 	case UBYTE:
995 		s = "ubyte";
996 		break;
997 	case USHORT:
998 		s = "ushort";
999 		break;
1000 	case ULONG:
1001 		s = "ulong";
1002 		break;
1003 	case ULLONG:
1004 		s = "ullong";
1005 		break;
1006 	case STR:
1007 		return ("string");
1008 	default:
1009 		/* more of an emergency measure .. */
1010 		(void) sprintf(buf, "%d", ep->e_type);
1011 		return (buf);
1012 	}
1013 	if (ep->e_mask) {
1014 		(void) snprintf(buf, sizeof (buf), "%s&0x%llx", s, ep->e_mask);
1015 		return (buf);
1016 	} else
1017 		return (s);
1018 }
1019 
1020 static char
1021 op_to_name(char op)
1022 {
1023 	char c;
1024 
1025 	switch (op & ~SUB) {
1026 
1027 	case EQ:
1028 	case STRC:
1029 		c = '=';
1030 		break;
1031 
1032 	case GT:
1033 		c = '>';
1034 		break;
1035 
1036 	case LT:
1037 		c = '<';
1038 		break;
1039 
1040 	case ANY:
1041 		c = 'x';
1042 		break;
1043 
1044 	case AND:
1045 		c = '&';
1046 		break;
1047 
1048 	case NSET:
1049 		c = '^';
1050 		break;
1051 
1052 	default:
1053 		c = '?';
1054 		break;
1055 	}
1056 
1057 	return (c);
1058 }
1059 
1060 /*
1061  * f_prtmtab - Prints out a header, then entries from both magic
1062  *	tables, mtab1 and mtab2, if any exist.
1063  */
1064 void
1065 f_prtmtab(void)
1066 {
1067 	Entry	*mtab;
1068 	Entry	*ep;
1069 	int	count;
1070 
1071 	(void) printf("%-7s %-7s %-10s %-7s %-11s %s\n",
1072 	    "level", "off", "type", "opcode", "value", "string");
1073 	for (mtab = mtab1, count = 1; count <= 2; count++, mtab = mtab2) {
1074 		if (mtab == (Entry *)NULL) {
1075 			continue;
1076 		}
1077 		for (ep = mtab; ep->e_off != -1L; ep++) {
1078 			(void) printf("%-7d %-7ld %-10s %-7c ",
1079 			    ep->e_level,
1080 			    ep->e_off, type_to_name(ep),
1081 			    op_to_name(ep->e_opcode));
1082 			if (ep->e_type == STR) {
1083 				showstr(ep->e_value.str, 10);
1084 			} else {	/* numeric */
1085 				(void) printf("%-#11llo", ep->e_value.num);
1086 			}
1087 			(void) printf(" %s", ep->e_str);
1088 			if (ep->e_opcode & SUB)
1089 				(void) printf("\tsubst");
1090 			(void) printf("\n");
1091 		}
1092 	}
1093 }
1094 
1095 intmax_t
1096 f_getmaxoffset(int first)
1097 {
1098 	Entry *mtab;
1099 	Entry *ep;
1100 	intmax_t cur;
1101 	intmax_t max = 0;
1102 
1103 	if (first) {
1104 		mtab = mtab1;
1105 	} else {
1106 		mtab = mtab2;
1107 	}
1108 	if (mtab == (Entry *)NULL) {
1109 		return (0);
1110 	}
1111 	for (ep = mtab; ep->e_off != -1L; ep++) {
1112 		cur = ep->e_off;
1113 		switch (ep->e_type) {
1114 		case STR:
1115 			cur += strlen(ep->e_value.str);
1116 			break;
1117 		case BYTE:
1118 		case UBYTE:
1119 			cur += sizeof (uchar_t);
1120 			break;
1121 		case SHORT:
1122 		case USHORT:
1123 			cur += sizeof (uint16_t);
1124 			break;
1125 		case LONG:
1126 		case ULONG:
1127 			cur += sizeof (uint32_t);
1128 			break;
1129 		case LLONG:
1130 		case ULLONG:
1131 			cur += sizeof (uint64_t);
1132 			break;
1133 		}
1134 		if (cur <= INT_MAX && cur > max) {
1135 			max = cur;
1136 		}
1137 	}
1138 
1139 	return (max);
1140 }
1141