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
81struct	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 */
95extern const char	*File;
96
97typedef	struct entry	Entry;
98
99static 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	 */
105static Entry	*mtab2;
106
107static Entry	*mend1;	/* one past last-allocated entry in mtab1 */
108static Entry	*mend2;	/* one past last-allocated entry in mtab2 */
109
110static Entry	*ep1;	/* current entry in mtab1 */
111static Entry	*ep2;	/* current entry in mtab2 */
112
113static char *
114getstr(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
220int
221f_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 */
535int
536f_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
915static void
916showstr(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
975static char *
976type_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
1020static char
1021op_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 */
1064void
1065f_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
1095intmax_t
1096f_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