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