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