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++ = NULL;
 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++ = NULL;
 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) == NULL) {
 333                                         /* d */
 334                                         ep->e_type = LONG;
 335                                 } else if (*(p+2) == NULL) {    /* 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) == NULL) {
 381                                         /* u */
 382                                         ep->e_type = ULONG;
 383                                 } else if (*(p+2) == NULL) {    /* 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++ = NULL;
 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 }