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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 31 /* All Rights Reserved */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <ctype.h> 39 #include <errno.h> 40 #include <limits.h> 41 #include <inttypes.h> 42 #include <sys/types.h> 43 #include <libintl.h> 44 45 /* 46 * Types 47 */ 48 49 #define BYTE 1 50 #define SHORT 2 51 #define LONG 4 52 #define LLONG 8 53 #define UBYTE 16 54 #define USHORT 32 55 #define ULONG 64 56 #define ULLONG 128 57 #define STR 256 58 59 /* 60 * Opcodes 61 */ 62 63 #define EQ 0 64 #define GT 1 65 #define LT 2 66 #define STRC 3 /* string compare */ 67 #define ANY 4 68 #define AND 5 69 #define NSET 6 /* True if bit is not set */ 70 #define SUB 64 /* or'ed in, SUBstitution string, for example */ 71 /* %ld, %s, %lo mask: with bit 6 on, used to locate */ 72 /* print formats */ 73 /* 74 * Misc 75 */ 76 77 #define BSZ 128 78 #define NENT 200 79 80 /* 81 * Structure of magic file entry 82 */ 83 84 struct entry { 85 char e_level; /* 0 or 1 */ 86 off_t e_off; /* in bytes */ 87 uint32_t e_type; /* BYTE, SHORT, STR, et al */ 88 char e_opcode; /* EQ, GT, LT, ANY, AND, NSET */ 89 uint64_t e_mask; /* if non-zero, mask value with this */ 90 union { 91 uint64_t num; 92 char *str; 93 } e_value; 94 const char *e_str; 95 }; 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) 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 perror(gettext("magic table string allocation")); 124 return (NULL); 125 } 126 127 s = newstr; 128 while (*p != '\0') { 129 if (*p != '\\') { 130 *s++ = *p++; 131 continue; 132 } 133 p++; 134 if (*p == '\0') 135 break; 136 if (isdigit(*p)) { 137 if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) { 138 /* hex */ 139 base = 16; 140 } else { 141 base = 8; 142 } 143 errno = 0; 144 val = strtol(p, &p, base); 145 if (val > UCHAR_MAX || val < 0 || errno != 0) { 146 perror(gettext("magic table invalid " 147 "string value")); 148 return (NULL); 149 } 150 *s++ = (char)val; 151 } else { 152 /* escape the character */ 153 switch (*p) { 154 case 'n': 155 *s = '\n'; 156 break; 157 case 'r': 158 *s = '\r'; 159 break; 160 case 'a': 161 *s = '\a'; 162 break; 163 case 'b': 164 *s = '\b'; 165 break; 166 case 'f': 167 *s = '\f'; 168 break; 169 case 't': 170 *s = '\t'; 171 break; 172 case 'v': 173 *s = '\v'; 174 break; 175 default: 176 *s = *p; 177 break; 178 } 179 p++; 180 s++; 181 } 182 } 183 *s = '\0'; 184 return (newstr); 185 } 186 187 /* 188 * f_mkmtab - fills mtab array of magic table entries with 189 * values from the file magfile. 190 * May be called more than once if multiple magic 191 * files were specified. 192 * Stores entries sequentially in one of two magic 193 * tables: mtab1, if first = 1; mtab2 otherwise. 194 * 195 * If -c option is specified, cflg is non-zero, and 196 * f_mkmtab() reports on errors in the magic file. 197 * 198 * Two magic tables may need to be created. The first 199 * one (mtab1) contains magic entries to be checked before 200 * the programmatic default position-sensitive tests in 201 * def_position_tests(). 202 * The second one (mtab2) should start with the default 203 * /etc/magic file entries and is to be checked after 204 * the programmatic default position-sensitive tests in 205 * def_position_tests(). The parameter "first" would 206 * be 1 for the former set of tables, 0 for the latter 207 * set of magic tables. 208 * No mtab2 should be created if file will not be 209 * applying default tests; in that case, all magic table 210 * entries should be in mtab1. 211 * 212 * f_mkmtab returns 0 on success, -1 on error. The calling 213 * program is not expected to proceed after f_mkmtab() 214 * returns an error. 215 */ 216 217 int 218 f_mkmtab(char *magfile, int cflg, int first) 219 { 220 Entry *mtab; /* generic magic table pointer */ 221 Entry *ep; /* current magic table entry */ 222 Entry *mend; /* one past last-allocated entry of mtab */ 223 FILE *fp; 224 int lcnt = 0; 225 char buf[BSZ]; 226 size_t tbsize; 227 size_t oldsize; 228 229 if (first) { 230 mtab = mtab1; 231 mend = mend1; 232 ep = ep1; 233 } else { 234 mtab = mtab2; 235 mend = mend2; 236 ep = ep2; 237 } 238 239 /* mtab may have been allocated on a previous f_mkmtab call */ 240 if (mtab == (Entry *)NULL) { 241 mtab = (Entry *) calloc(sizeof (Entry), NENT); 242 if (mtab == (Entry *)NULL) { 243 (void) fprintf(stderr, 244 gettext("no memory for magic table\n")); 245 return (-1); 246 } 247 248 ep = mtab; 249 mend = &mtab[NENT]; 250 } 251 252 fp = fopen(magfile, "r"); 253 if (fp == NULL) { 254 (void) fprintf(stderr, 255 gettext("cannot open magic file <%s>.\n"), 256 magfile); 257 return (-1); 258 } 259 while (fgets(buf, BSZ, fp) != NULL) { 260 char *p = buf; 261 char *p2; 262 char *p3; 263 char opc; 264 265 /* 266 * ensure we have one extra entry allocated 267 * to mark end of the table, after the while loop 268 */ 269 if (ep >= (mend - 1)) { 270 oldsize = mend - mtab; 271 tbsize = (NENT + oldsize) * sizeof (Entry); 272 if ((mtab = realloc(mtab, tbsize)) == NULL) { 273 perror(gettext("magic table overflow")); 274 return (-1); 275 } else { 276 (void) memset(mtab + oldsize, 0, 277 sizeof (Entry) * NENT); 278 mend = &mtab[tbsize / sizeof (Entry)]; 279 ep = &mtab[oldsize-1]; 280 } 281 } 282 283 lcnt++; 284 if (*p == '\n' || *p == '#') 285 continue; 286 287 288 /* LEVEL */ 289 if (*p == '>') { 290 ep->e_level = 1; 291 p++; 292 } 293 /* OFFSET */ 294 p2 = strchr(p, '\t'); 295 if (p2 == NULL) { 296 if (cflg) 297 (void) fprintf(stderr, 298 gettext("fmt error, no tab after %s on " 299 "line %d of %s\n"), p, lcnt, magfile); 300 continue; 301 } 302 *p2++ = NULL; 303 ep->e_off = strtol((const char *)p, (char **)NULL, 0); 304 while (*p2 == '\t') 305 p2++; 306 /* TYPE */ 307 p = p2; 308 p2 = strchr(p, '\t'); 309 if (p2 == NULL) { 310 if (cflg) 311 (void) fprintf(stderr, 312 gettext("fmt error, no tab after %s on " 313 "line %d of %s\n"), p, lcnt, magfile); 314 continue; 315 } 316 *p2++ = NULL; 317 p3 = strchr(p, '&'); 318 if (p3 != NULL) { 319 *p3++ = '\0'; 320 ep->e_mask = strtoull((const char *)p3, (char **)NULL, 321 0); /* returns 0 or ULLONG_MAX on error */ 322 } else { 323 ep->e_mask = 0ULL; 324 } 325 switch (*p) { 326 case 'd': 327 if (*(p+1) == NULL) { 328 /* d */ 329 ep->e_type = LONG; 330 } else if (*(p+2) == NULL) { /* d? */ 331 switch (*(p+1)) { 332 case 'C': 333 case '1': 334 /* dC, d1 */ 335 ep->e_type = BYTE; 336 break; 337 case 'S': 338 case '2': 339 /* dS, d2 */ 340 ep->e_type = SHORT; 341 break; 342 case 'I': 343 case 'L': 344 case '4': 345 /* dI, dL, d4 */ 346 ep->e_type = LONG; 347 break; 348 case '8': 349 /* d8 */ 350 ep->e_type = LLONG; 351 break; 352 default: 353 ep->e_type = LONG; 354 break; 355 } 356 } 357 break; 358 case 'l': 359 if (*(p+1) == 'l') { /* llong */ 360 ep->e_type = LLONG; 361 } else { /* long */ 362 ep->e_type = LONG; 363 } 364 break; 365 case 's': 366 if (*(p+1) == 'h') { 367 /* short */ 368 ep->e_type = SHORT; 369 } else { 370 /* s or string */ 371 ep->e_type = STR; 372 } 373 break; 374 case 'u': 375 if (*(p+1) == NULL) { 376 /* u */ 377 ep->e_type = ULONG; 378 } else if (*(p+2) == NULL) { /* u? */ 379 switch (*(p+1)) { 380 case 'C': 381 case '1': 382 /* uC, u1 */ 383 ep->e_type = UBYTE; 384 break; 385 case 'S': 386 case '2': 387 /* uS, u2 */ 388 ep->e_type = USHORT; 389 break; 390 case 'I': 391 case 'L': 392 case '4': 393 /* uI, uL, u4 */ 394 ep->e_type = ULONG; 395 break; 396 case '8': 397 /* u8 */ 398 ep->e_type = ULLONG; 399 break; 400 default: 401 ep->e_type = ULONG; 402 break; 403 } 404 } else { /* u?* */ 405 switch (*(p+1)) { 406 case 'b': /* ubyte */ 407 ep->e_type = UBYTE; 408 break; 409 case 's': /* ushort */ 410 ep->e_type = USHORT; 411 break; 412 case 'l': 413 if (*(p+2) == 'l') { 414 /* ullong */ 415 ep->e_type = ULLONG; 416 } else { 417 /* ulong */ 418 ep->e_type = ULONG; 419 } 420 break; 421 default: 422 /* default, same as "u" */ 423 ep->e_type = ULONG; 424 break; 425 } 426 } 427 break; 428 default: 429 /* retain (undocumented) default type */ 430 ep->e_type = BYTE; 431 break; 432 } 433 if (ep->e_type == 0) { 434 ep->e_type = BYTE; /* default */ 435 } 436 while (*p2 == '\t') 437 p2++; 438 /* OP-VALUE */ 439 p = p2; 440 p2 = strchr(p, '\t'); 441 if (p2 == NULL) { 442 if (cflg) 443 (void) fprintf(stderr, 444 gettext("fmt error, no tab after %s on " 445 "line %d of %s\n"), p, lcnt, magfile); 446 continue; 447 } 448 *p2++ = NULL; 449 if (ep->e_type != STR) { 450 opc = *p++; 451 switch (opc) { 452 case '=': 453 ep->e_opcode = EQ; 454 break; 455 456 case '>': 457 ep->e_opcode = GT; 458 break; 459 460 case '<': 461 ep->e_opcode = LT; 462 break; 463 464 case 'x': 465 ep->e_opcode = ANY; 466 break; 467 468 case '&': 469 ep->e_opcode = AND; 470 break; 471 472 case '^': 473 ep->e_opcode = NSET; 474 break; 475 default: /* EQ (i.e. 0) is default */ 476 p--; /* since global ep->e_opcode=0 */ 477 } 478 } 479 if (ep->e_opcode != ANY) { 480 if (ep->e_type != STR) { 481 ep->e_value.num = strtoull((const char *)p, 482 (char **)NULL, 0); 483 } else if ((ep->e_value.str = getstr(p)) == NULL) { 484 return (-1); 485 } 486 } 487 p2 += strspn(p2, "\t"); 488 /* STRING */ 489 if ((ep->e_str = strdup(p2)) == NULL) { 490 perror(gettext("magic table message allocation")); 491 return (-1); 492 } else { 493 if ((p = strchr(ep->e_str, '\n')) != NULL) 494 *p = '\0'; 495 if (strchr(ep->e_str, '%') != NULL) 496 ep->e_opcode |= SUB; 497 } 498 ep++; 499 } /* end while (fgets) */ 500 501 ep->e_off = -1L; /* mark end of table */ 502 if (first) { 503 mtab1 = mtab; 504 mend1 = mend; 505 ep1 = ep; 506 } else { 507 mtab2 = mtab; 508 mend2 = mend; 509 ep2 = ep; 510 } 511 if (fclose(fp) == EOF) { 512 perror(magfile); 513 return (-1); 514 } 515 return (0); 516 } 517 518 /* 519 * Check for Magic Table entries in the file. 520 * 521 * Since there may be two sets of magic tables, first = 1 522 * for the first magic table (mtab1) and 0 for the second magic 523 * table (mtab2). 524 */ 525 int 526 f_ckmtab(char *buf, int bufsize, int first) 527 { 528 int result; 529 Entry *mtab; 530 Entry *ep; 531 char *p; 532 int lev1 = 0; 533 534 uint16_t u16_val; 535 uint32_t u32_val; 536 uint64_t u64_val; 537 538 if (first) { 539 mtab = mtab1; 540 } else { 541 mtab = mtab2; 542 } 543 544 if (mtab == (Entry *)NULL) { 545 return (0); /* no magic file tests in this table */ 546 } 547 548 for (ep = mtab; ep->e_off != -1L; ep++) { /* -1 offset marks end of */ 549 if (lev1) { /* valid magic file entries */ 550 if (ep->e_level != 1) 551 break; 552 } else if (ep->e_level == 1) { 553 continue; 554 } 555 if (ep->e_off > (off_t)bufsize) 556 continue; 557 p = &buf[ep->e_off]; 558 switch (ep->e_type) { 559 case STR: 560 { 561 if (strncmp(p, ep->e_value.str, 562 strlen(ep->e_value.str))) 563 continue; 564 if (lev1) { 565 (void) putchar(' '); 566 } 567 if (ep->e_opcode & SUB) 568 (void) printf(ep->e_str, 569 ep->e_value.str); 570 else 571 (void) printf(ep->e_str); 572 lev1 = 1; 573 continue; 574 /* 575 * We've matched the string and printed the message; 576 * no STR processing occurs beyond this point. 577 */ 578 } 579 580 case BYTE: 581 case UBYTE: 582 u64_val = (uint64_t)(uint8_t)(*p); 583 break; 584 585 case SHORT: 586 case USHORT: 587 (void) memcpy(&u16_val, p, sizeof (uint16_t)); 588 u64_val = (uint64_t)u16_val; 589 break; 590 591 case LONG: 592 case ULONG: 593 (void) memcpy(&u32_val, p, sizeof (uint32_t)); 594 u64_val = (uint64_t)u32_val; 595 break; 596 597 case LLONG: 598 case ULLONG: 599 (void) memcpy(&(u64_val), p, sizeof (uint64_t)); 600 break; 601 602 } 603 604 if (ep->e_mask) { 605 u64_val &= ep->e_mask; 606 } 607 608 /* 609 * Compare the values according to the size and sign 610 * of the type. For =, &, and ^ operators, the sign 611 * does not have any effect, so these are always compared 612 * unsigned. Only for < and > operators is the 613 * sign significant. 614 * If the file value was masked, the compare should 615 * be unsigned. 616 */ 617 switch (ep->e_opcode & ~SUB) { 618 case EQ: 619 switch (ep->e_type) { 620 case BYTE: 621 case UBYTE: 622 if ((uint8_t)u64_val != 623 (uint8_t)(ep->e_value.num)) 624 continue; 625 break; 626 case SHORT: 627 case USHORT: 628 if ((uint16_t)u64_val != 629 (uint16_t)(ep->e_value.num)) 630 continue; 631 break; 632 case LONG: 633 case ULONG: 634 if ((uint32_t)u64_val != 635 (uint32_t)(ep->e_value.num)) 636 continue; 637 break; 638 case LLONG: 639 case ULLONG: 640 if (u64_val != ep->e_value.num) 641 continue; 642 break; 643 default: 644 continue; 645 } 646 break; 647 case GT: 648 switch (ep->e_type) { 649 case BYTE: 650 if (ep->e_mask == 0) { 651 if ((int8_t)u64_val <= 652 (int8_t)(ep->e_value.num)) 653 continue; 654 break; 655 } 656 /*FALLTHROUGH*/ 657 case UBYTE: 658 if ((uint8_t)u64_val <= 659 (uint8_t)(ep->e_value.num)) 660 continue; 661 break; 662 case SHORT: 663 if (ep->e_mask == 0) { 664 if ((int16_t)u64_val <= 665 (int16_t)(ep->e_value.num)) 666 continue; 667 break; 668 } 669 /*FALLTHROUGH*/ 670 case USHORT: 671 if ((uint16_t)u64_val <= 672 (uint16_t)(ep->e_value.num)) 673 continue; 674 break; 675 case LONG: 676 if (ep->e_mask == 0) { 677 if ((int32_t)u64_val <= 678 (int32_t)(ep->e_value.num)) 679 continue; 680 break; 681 } 682 /*FALLTHROUGH*/ 683 case ULONG: 684 if ((uint32_t)u64_val <= 685 (uint32_t)(ep->e_value.num)) 686 continue; 687 break; 688 case LLONG: 689 if (ep->e_mask == 0) { 690 if ((int64_t)u64_val <= 691 (int64_t)(ep->e_value.num)) 692 continue; 693 break; 694 } 695 /*FALLTHROUGH*/ 696 case ULLONG: 697 if (u64_val <= ep->e_value.num) 698 continue; 699 break; 700 default: 701 continue; 702 } 703 break; 704 case LT: 705 switch (ep->e_type) { 706 case BYTE: 707 if (ep->e_mask == 0) { 708 if ((int8_t)u64_val >= 709 (int8_t)(ep->e_value.num)) 710 continue; 711 break; 712 } 713 /*FALLTHROUGH*/ 714 case UBYTE: 715 if ((uint8_t)u64_val >= 716 (uint8_t)(ep->e_value.num)) 717 continue; 718 break; 719 case SHORT: 720 if (ep->e_mask == 0) { 721 if ((int16_t)u64_val >= 722 (int16_t)(ep->e_value.num)) 723 continue; 724 break; 725 } 726 /*FALLTHROUGH*/ 727 case USHORT: 728 if ((uint16_t)u64_val >= 729 (uint16_t)(ep->e_value.num)) 730 continue; 731 break; 732 case LONG: 733 if (ep->e_mask == 0) { 734 if ((int32_t)u64_val >= 735 (int32_t)(ep->e_value.num)) 736 continue; 737 break; 738 } 739 /*FALLTHROUGH*/ 740 case ULONG: 741 if ((uint32_t)u64_val >= 742 (uint32_t)(ep->e_value.num)) 743 continue; 744 break; 745 case LLONG: 746 if (ep->e_mask == 0) { 747 if ((int64_t)u64_val >= 748 (int64_t)(ep->e_value.num)) 749 continue; 750 break; 751 } 752 /*FALLTHROUGH*/ 753 case ULLONG: 754 if (u64_val >= ep->e_value.num) 755 continue; 756 break; 757 default: 758 continue; 759 } 760 break; 761 case AND: 762 switch (ep->e_type) { 763 case BYTE: 764 case UBYTE: 765 if (((uint8_t)u64_val & 766 (uint8_t)(ep->e_value.num)) == 767 (uint8_t)(ep->e_value.num)) 768 break; 769 continue; 770 case SHORT: 771 case USHORT: 772 if (((uint16_t)u64_val & 773 (uint16_t)(ep->e_value.num)) == 774 (uint16_t)(ep->e_value.num)) 775 break; 776 continue; 777 case LONG: 778 case ULONG: 779 if (((uint32_t)u64_val & 780 (uint32_t)(ep->e_value.num)) == 781 (uint32_t)(ep->e_value.num)) 782 break; 783 continue; 784 case LLONG: 785 case ULLONG: 786 if ((u64_val & ep->e_value.num) == 787 ep->e_value.num) 788 break; 789 continue; 790 default: 791 continue; 792 } 793 break; 794 case NSET: 795 switch (ep->e_type) { 796 case BYTE: 797 case UBYTE: 798 if (((uint8_t)u64_val & 799 (uint8_t)(ep->e_value.num)) != 800 (uint8_t)(ep->e_value.num)) 801 break; 802 continue; 803 case SHORT: 804 case USHORT: 805 if (((uint16_t)u64_val & 806 (uint16_t)(ep->e_value.num)) != 807 (uint16_t)(ep->e_value.num)) 808 break; 809 continue; 810 case LONG: 811 case ULONG: 812 if (((uint32_t)u64_val & 813 (uint32_t)(ep->e_value.num)) != 814 (uint32_t)(ep->e_value.num)) 815 break; 816 continue; 817 case LLONG: 818 case ULLONG: 819 if ((u64_val & ep->e_value.num) != 820 ep->e_value.num) 821 break; 822 continue; 823 default: 824 continue; 825 } 826 break; 827 case ANY: /* matches anything */ 828 break; 829 default: /* shouldn't occur; ignore it */ 830 continue; 831 } 832 if (lev1) 833 (void) putchar(' '); 834 if (ep->e_opcode & SUB) { 835 switch (ep->e_type) { 836 case LLONG: 837 #ifdef XPG4 838 if (ep->e_mask == 0) { 839 (void) printf(ep->e_str, 840 (int64_t)u64_val); 841 break; 842 } 843 #endif /* XPG4 */ 844 /*FALLTHROUGH*/ 845 case ULLONG: 846 (void) printf(ep->e_str, u64_val); 847 break; 848 case LONG: 849 #ifdef XPG4 850 if (ep->e_mask == 0) { 851 (void) printf(ep->e_str, 852 (int32_t)u64_val); 853 break; 854 } 855 #endif /* XPG4 */ 856 /*FALLTHROUGH*/ 857 case ULONG: 858 (void) printf(ep->e_str, 859 (uint32_t)u64_val); 860 break; 861 case SHORT: 862 #ifdef XPG4 863 if (ep->e_mask == 0) { 864 (void) printf(ep->e_str, 865 (int16_t)u64_val); 866 break; 867 } 868 #endif /* XPG4 */ 869 /*FALLTHROUGH*/ 870 case USHORT: 871 (void) printf(ep->e_str, 872 (uint16_t)u64_val); 873 break; 874 case BYTE: 875 #ifdef XPG4 876 if (ep->e_mask == 0) { 877 (void) printf(ep->e_str, 878 (int8_t)u64_val); 879 break; 880 } 881 #endif /* XPG4 */ 882 /*FALLTHROUGH*/ 883 case UBYTE: 884 (void) printf(ep->e_str, 885 (uint8_t)u64_val); 886 break; 887 case STR: 888 /* 889 * Note: Currently can't get type 890 * STR here because we already 891 * did a 'continue' out of the 892 * loop earlier for case STR 893 */ 894 break; 895 } 896 } else 897 (void) printf(ep->e_str); 898 lev1 = 1; 899 } 900 result = lev1 ? (int)(1 + ep - mtab) : 0; 901 902 return (result); 903 } 904 905 static void 906 showstr(char *s, int width) 907 { 908 char c; 909 910 while ((c = *s++) != '\0') 911 if (c >= 040 && c < 0176) { 912 (void) putchar(c); 913 width--; 914 } else { 915 (void) putchar('\\'); 916 switch (c) { 917 918 case '\n': 919 (void) putchar('n'); 920 width -= 2; 921 break; 922 923 case '\r': 924 (void) putchar('r'); 925 width -= 2; 926 break; 927 928 case '\a': 929 (void) putchar('a'); 930 width -= 2; 931 break; 932 933 case '\b': 934 (void) putchar('b'); 935 width -= 2; 936 break; 937 938 case '\t': 939 (void) putchar('t'); 940 width -= 2; 941 break; 942 943 case '\f': 944 (void) putchar('f'); 945 width -= 2; 946 break; 947 948 case '\v': 949 (void) putchar('v'); 950 width -= 2; 951 break; 952 953 default: 954 (void) printf("%.3o", c & 0377); 955 width -= 4; 956 break; 957 } 958 } 959 while (width >= 0) { 960 (void) putchar(' '); 961 width--; 962 }; 963 } 964 965 static char * 966 type_to_name(Entry *ep) 967 { 968 static char buf[20]; 969 char *s; 970 971 switch (ep->e_type) { 972 case BYTE: 973 s = "byte"; 974 break; 975 case SHORT: 976 s = "short"; 977 break; 978 case LONG: 979 s = "long"; 980 break; 981 case LLONG: 982 s = "llong"; 983 break; 984 case UBYTE: 985 s = "ubyte"; 986 break; 987 case USHORT: 988 s = "ushort"; 989 break; 990 case ULONG: 991 s = "ulong"; 992 break; 993 case ULLONG: 994 s = "ullong"; 995 break; 996 case STR: 997 return ("string"); 998 default: 999 /* more of an emergency measure .. */ 1000 (void) sprintf(buf, "%d", ep->e_type); 1001 return (buf); 1002 } 1003 if (ep->e_mask) { 1004 (void) snprintf(buf, sizeof (buf), "%s&0x%llx", s, ep->e_mask); 1005 return (buf); 1006 } else 1007 return (s); 1008 } 1009 1010 static char 1011 op_to_name(char op) 1012 { 1013 char c; 1014 1015 switch (op & ~SUB) { 1016 1017 case EQ: 1018 case STRC: 1019 c = '='; 1020 break; 1021 1022 case GT: 1023 c = '>'; 1024 break; 1025 1026 case LT: 1027 c = '<'; 1028 break; 1029 1030 case ANY: 1031 c = 'x'; 1032 break; 1033 1034 case AND: 1035 c = '&'; 1036 break; 1037 1038 case NSET: 1039 c = '^'; 1040 break; 1041 1042 default: 1043 c = '?'; 1044 break; 1045 } 1046 1047 return (c); 1048 } 1049 1050 /* 1051 * f_prtmtab - Prints out a header, then entries from both magic 1052 * tables, mtab1 and mtab2, if any exist. 1053 */ 1054 void 1055 f_prtmtab(void) 1056 { 1057 Entry *mtab; 1058 Entry *ep; 1059 int count; 1060 1061 (void) printf("%-7s %-7s %-10s %-7s %-11s %s\n", 1062 "level", "off", "type", "opcode", "value", "string"); 1063 for (mtab = mtab1, count = 1; count <= 2; count++, mtab = mtab2) { 1064 if (mtab == (Entry *)NULL) { 1065 continue; 1066 } 1067 for (ep = mtab; ep->e_off != -1L; ep++) { 1068 (void) printf("%-7d %-7ld %-10s %-7c ", 1069 ep->e_level, 1070 ep->e_off, type_to_name(ep), 1071 op_to_name(ep->e_opcode)); 1072 if (ep->e_type == STR) { 1073 showstr(ep->e_value.str, 10); 1074 } else { /* numeric */ 1075 (void) printf("%-#11llo", ep->e_value.num); 1076 } 1077 (void) printf(" %s", ep->e_str); 1078 if (ep->e_opcode & SUB) 1079 (void) printf("\tsubst"); 1080 (void) printf("\n"); 1081 } 1082 } 1083 } 1084 1085 intmax_t 1086 f_getmaxoffset(int first) 1087 { 1088 Entry *mtab; 1089 Entry *ep; 1090 intmax_t cur; 1091 intmax_t max = 0; 1092 1093 if (first) { 1094 mtab = mtab1; 1095 } else { 1096 mtab = mtab2; 1097 } 1098 if (mtab == (Entry *)NULL) { 1099 return (0); 1100 } 1101 for (ep = mtab; ep->e_off != -1L; ep++) { 1102 cur = ep->e_off; 1103 switch (ep->e_type) { 1104 case STR: 1105 cur += strlen(ep->e_value.str); 1106 break; 1107 case BYTE: 1108 case UBYTE: 1109 cur += sizeof (uchar_t); 1110 break; 1111 case SHORT: 1112 case USHORT: 1113 cur += sizeof (uint16_t); 1114 break; 1115 case LONG: 1116 case ULONG: 1117 cur += sizeof (uint32_t); 1118 break; 1119 case LLONG: 1120 case ULLONG: 1121 cur += sizeof (uint64_t); 1122 break; 1123 } 1124 if (cur <= INT_MAX && cur > max) { 1125 max = cur; 1126 } 1127 } 1128 1129 return (max); 1130 } 1131