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