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