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 * 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 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 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 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 * 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 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 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 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