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 *
getstr(char * p,char * file)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
f_mkmtab(char * magfile,int cflg,int first)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
f_ckmtab(char * buf,int bufsize,int first)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
showstr(char * s,int width)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 *
type_to_name(Entry * ep)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
op_to_name(char op)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
f_prtmtab(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
f_getmaxoffset(int first)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